/*******************************************************************************
 * Copyright (c) 2010, 2017 西安秦晔信息科技有限公司
 * Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 *******************************************************************************/
package com.qinyeit.serviceapp.service.branchs;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qinyeit.serviceapp.entity.*;
import com.qinyeit.serviceapp.entity.enums.*;
import com.qinyeit.serviceapp.exception.BusinessRunTimeException;
import com.qinyeit.serviceapp.redis.RedisKeyHelper;
import com.qinyeit.serviceapp.repository.dishes.DishesRepository;
import com.qinyeit.serviceapp.repository.materials.MaterialRepository;
import com.qinyeit.serviceapp.repository.organization.BranchRepository;
import com.qinyeit.serviceapp.service.branchstores.BranchSupplierService;
import com.qinyeit.serviceapp.service.branchstores.BranchWarehouseService;
import com.qinyeit.serviceapp.service.branchstores.MaterialCostDetailService;
import com.qinyeit.serviceapp.service.branchstores.MaterialCostService;
import com.qinyeit.serviceapp.service.dishes.*;
import com.qinyeit.serviceapp.service.materials.MaterialCategoryService;
import com.qinyeit.serviceapp.service.materials.MaterialService;
import com.qinyeit.serviceapp.service.materials.MaterialUnitService;
import com.qinyeit.serviceapp.service.materials.PurchaseSpecService;
import com.qinyeit.serviceapp.service.members.*;
import com.qinyeit.serviceapp.service.organization.BranchService;
import com.qinyeit.serviceapp.service.pays.DiscountDetailService;
import com.qinyeit.serviceapp.service.pays.DiscountPlanService;
import com.qinyeit.serviceapp.utils.SearchUtils;
import com.qinyetech.springstage.core.entity.search.SearchFilterHelper;
import com.qinyetech.springstage.core.entity.search.SearchOperator;
import com.qinyetech.springstage.core.entity.search.Searchable;
import com.qinyetech.springstage.core.lang.QyMap;
import com.qinyetech.springstage.core.lang.StringUtils;
import com.qinyetech.springstage.core.repository.jdbc.PageNamedParameterJdbcTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.Comparator.comparingLong;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;

/**
 * 单店版 数据下发
 */
@Slf4j
@Service
public class BranchDataReleasedServiceImpl {

    @Resource(name = "branchJdbcTemplate")
    private PageNamedParameterJdbcTemplate branchJdbcTemplate;
    @Autowired
    private PageNamedParameterJdbcTemplate jdbcTemplate;
    @Autowired
    private BranchRepository branchRepository;
    @Autowired
    private DishesRepository dishesRepository;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private DishesSpecificationRelationService dishesSpecificationRelationService;
    @Autowired
    private DishesSpecificationService dishesSpecificationService;
    @Autowired
    private DishesCategoryService dishesCategoryService;
    @Autowired
    private DishesMakeCategoryService dishesMakeCategoryService;
    @Autowired
    private DishesFeedCategoryService dishesFeedCategoryService;
    @Autowired
    private DishesMakeService dishesMakeService;
    @Autowired
    private DishesFeedService dishesFeedService;
    @Autowired
    private DishesUnitService dishesUnitService;
    @Autowired
    private DishesMakeRelationService dishesMakeRelationService;
    @Autowired
    private DishesPackageGroupService dishesPackageGroupService;
    @Autowired
    private DishesPackageDetailService dishesPackageDetailService;
    @Autowired
    private DishesFeedRelationService dishesFeedRelationService;
    @Autowired
    private DiscountDetailService discountDetailService;
    @Autowired
    private BranchWarehouseService branchWarehouseService;
    @Autowired
    private BranchSupplierService branchSupplierService;
    @Autowired
    private MaterialUnitService materialUnitService;
    @Autowired
    private MaterialCategoryService materialCategoryService;
    @Autowired
    private MaterialService materialService;
    @Autowired
    private PurchaseSpecService purchaseSpecService;
    @Autowired
    private MaterialCostService materialCostService;
    @Autowired
    private MaterialCostDetailService materialCostDetailService;
    @Autowired
    private DiscountPlanService discountPlanService;
    @Autowired
    private BranchService branchService;
    @Autowired
    private DeliveryDetailService deliveryDetailService;
    @Autowired
    private MemberCardTypeService memberCardTypeService;
    @Autowired
    private MemberCardService memberCardService;
    @Autowired
    private DeliveryRecordService deliveryRecordService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private VipRecordService vipRecordService;
    @Autowired
    private DishesService dishesService;
    @Autowired
    private MaterialRepository materialRepository;
    @Autowired
    private MachiningRelationService machiningRelationService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private DishesExtendService dishesExtendService;


    /**
     * 保存会员卡类型新添的的门店的会员信息和会员卡信息
     * @param insertIds
     * @param cardType
     */
    public void saveOtherMemberAndMemberCard(List<Long> insertIds, MemberCardType cardType) {
        Set<Long> merchantIds = changeMerchants(insertIds);
        //查找会员卡信息
        String sql = "SELECT * from member_cards where merchant_group_id = :merchantGroupId and type_id = :typeId and vip_id is not null";
        QyMap params = QyMap.map("merchantGroupId",cardType.getMerchantGroupId()).setv("typeId",cardType.getId());
        RowMapper<MemberCard> memberCard = new BeanPropertyRowMapper<>(MemberCard.class);
        List<MemberCard> memberCardList = jdbcTemplate.query(sql,params,memberCard);
        List<Long> memberIds = memberCardList.stream().map(MemberCard::getVipId).collect(Collectors.toList())
                .stream().distinct().collect(Collectors.toList());
        Map<Long,List<MemberCard>> longListMap = memberCardList.stream().collect(Collectors.groupingBy(x->x.getVipId()));
        Member member = null;
        Long mid;
        List<MemberCard> cardList = null;
        MemberCard mc = null;
        if (CollectionUtils.isNotEmpty(merchantIds)){
            for (Long merchantId : merchantIds) {
                if (CollectionUtils.isNotEmpty(memberIds)){
                    for (Long memberId : memberIds) {
                        member = memberService.findById(memberId);
                        mid = updateMember(merchantId,member);
                        //跟新会员信息
                        cardList = longListMap.get(memberId);
                        if (CollectionUtils.isNotEmpty(cardList)){
                            for (MemberCard card : cardList) {
                                mc = memberCardService.findById(card.getId());
                                updateMemberCard(merchantId,mc,mid);
                            }
                        }
                    }

                }
            }
        }


    }



    /**
     * 修改会员信息
     * @param data  data:{vipId:1,merchantId:1,groupId:1}
     */
    public void memberUpdate(JSONObject data) {
        Long merchantGroupId = data.getLong("groupId");
        Long vipId = data.getLong("vipId");
        Long merchantId = data.getLong("merchantId");

        if(vipId==null || merchantGroupId==null || merchantId==null){
            return;
        }

        //查询会员信息
        QyMap vipMap = getBranchMemberById(vipId);
        //保存/编辑会员
        Member member = memberService.updateMember(vipMap,merchantGroupId,"");
        //修改其他门店的会员信息

        QyMap params = QyMap.map("birthday",member.getBirthday())
                .setv("birthday_type",member.getBirthdayType())
                .setv("card_no",member.getCardNo())
                .setv("consume_amount",member.getConsumeAmount())
                .setv("consume_count",member.getConsumeCount())
                .setv("consume_time",member.getConsumeTime())
                .setv("gender",member.getGender().getKey())
                .setv("name",member.getName())
                .setv("phone",member.getPhone())
                .setv("source",member.getSource())
                .setv("state",member.getState().getKey())
                .setv("uuid",member.getUuid());

        String sql = "UPDATE members SET birthday=:birthday,birthday_type=:birthday_type,card_no=:card_no,\n" +
                "consume_amount=:consume_amount,consume_count=:consume_count,consume_time=:consume_time,\n" +
                "gender=:gender,name=:name,source=:source,state=:state,phone=:phone\n" +
                "WHERE uuid = :uuid";
        branchJdbcTemplate.update(sql,params);

    }


    /**
     * 开卡
     * @param data data:{cardId:1,vipId:1,recordId:1,merchantId:1,groupId:1}
     */
    public void openCard(JSONObject data){
        Long merchantGroupId = data.getLong("groupId");
        Long cardId = data.getLong("cardId");
        Long vipId = data.getLong("vipId");
        Long recordId = data.getLong("recordId");
        Long merchantId = data.getLong("merchantId");
        Member member = null;
        String sql ;
        QyMap params;
        MemberCard memberCard=null;
        VipRecord record = null;
        //会员卡信息
        sql = "SELECT * from member_cards where id = :cardId";
        params = QyMap.map("cardId",cardId);
        Map<String,Object> cardData = branchJdbcTemplate.queryForMap(sql,params);
        QyMap cardMap = QyMap.WRAP(cardData);

        Searchable searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
        searchable.addSearchParam("no_eq",cardMap.getString("no"));
        memberCard = memberCardService.findOne(searchable);

        if (memberCard==null){
            log.info("会员卡类型空 ");
            return ;
        }

        //会员卡类型适用门店
        List<Long> brands = memberCardTypeService.getBranchList(memberCard.getType().getId(),merchantGroupId);
        Set<Long> merchantIds = changeMerchants(brands);
        merchantIds.remove(merchantId);
//        log.info("剩余 ： ---- {}",merchantIds);
        Branch branch = branchService.getBranchByMerchantId(merchantId,merchantGroupId);
//        log.info("发生门店：{}",branch.getName());
        if(vipId!=null){
            //查询会员信息
            QyMap vipMap = getBranchMemberById(vipId);
            //保存/编辑会员
            member = memberService.updateMember(vipMap,merchantGroupId,branch.getName());

        }
        memberCard = memberCardService.bindVip(member,merchantGroupId,cardMap,memberCard);
        if (recordId!=null){
            //会员操作记录
            sql = "SELECT * from vip_records where id=:recordId";
            params = QyMap.map("recordId",data.getLong("recordId"));
            Map<String,Object> recordData = branchJdbcTemplate.queryForMap(sql,params);

            QyMap recordMap = QyMap.WRAP(recordData);

            record = vipRecordService.saveRecord(recordMap,merchantGroupId,branch.getName());
        }


//        log.info("剩余门店 ： {}",merchantIds);
        //保存其余门店的信息
        if (CollectionUtils.isNotEmpty(merchantIds)){
            Long memberId = null;
            Long memberCardId = null;
            for (Long id : merchantIds) {
                //保存 或编辑 会员
                if (vipId!=null){
                    memberId = updateMember(id,member);
                }

                //保存会员卡或者编辑会员卡信息
                memberCardId = updateMemberCard(id,memberCard,memberId);
                if (recordId!=null){
                    //保存会员操作记录
                    saveVipRecord(id,record);
                }

            }
        }

    }

    /**
     * 根据会员id获取会员信息
     * @param vipId 单店系统会员id
     * @return
     */
    private QyMap getBranchMemberById(Long vipId) {
        String sql;
        QyMap params;
        sql = "SELECT * from members where id = :vipId";
        params = QyMap.map("vipId",vipId);
        Map<String,Object> vipData = branchJdbcTemplate.queryForMap(sql,params);
        return QyMap.WRAP(vipData);
    }

    /**
     * 保存会员操作记录
     * @param merchantId 商户id 27
     * @param record 记录信息
     */
    private void saveVipRecord(Long merchantId, VipRecord record) {
        String sql = "INSERT INTO vip_records (create_at,is_deleted,status,merchant_id,after_gift,after_point,after_value,amount,back_desc," +
                "befor_point,before_gift,before_value,card_mode,card_no,card_state,cast_back,deposit,gift_point,gift_value,operator_name," +
                "order_no,pay_type,platform,remark,target_no,undo_time,uuid,vip_name,vip_phone,card_type,type)\n" +
                "VALUES(now(),0,0,:merchant_id,:after_gift,:after_point,:after_value,:amount,:back_desc," +
                ":befor_point,:before_gift,:before_value,:card_mode,:card_no,:card_state,:cast_back,:deposit,:gift_point,:gift_value,:operator_name," +
                ":order_no,:pay_type,:platform,:remark,:target_no,:undo_time,:uuid,:vip_name,:vip_phone,:card_type,:type) ";
        QyMap map = QyMap.map("merchant_id",merchantId)
                .setv("after_gift",record.getAfterGift())
                .setv("after_point",record.getAfterPoint())
                .setv("after_value",record.getAfterValue())
                .setv("amount",record.getAmount())
                .setv("back_desc",record.getBackDesc())
                .setv("befor_point",record.getBeforPoint())
                .setv("before_gift",record.getBeforeGift())
                .setv("before_value",record.getBeforeValue())
                .setv("card_mode",record.getCardMode()==null?null:record.getCardMode().getKey())
                .setv("card_no",record.getCardNo())
                .setv("card_state",record.getCardState()==null?null:record.getCardState().getKey())
                .setv("cast_back",record.getCastBack())
                .setv("deposit",record.getDeposit())
                .setv("gift_point",record.getGiftPoint())
                .setv("gift_value",record.getGiftValue())
                .setv("operator_name",record.getOperatorName())
                .setv("order_no",record.getOrderNo())
                .setv("pay_type",record.getPayType()==null?null:record.getPayType().getKey())
                .setv("platform",record.getPlatform()==null?null:record.getPlatform().getKey())
                .setv("remark",record.getRemark())
                .setv("target_no",record.getTargetNo())
                .setv("undo_time",record.getUndoTime())
                .setv("uuid",record.getUuid())
                .setv("vip_name",record.getVipName())
                .setv("vip_phone",record.getVipPhone())
                .setv("type",record.getType().getKey())
                .setv("card_type",record.getCardType());
            branchJdbcTemplate.update(sql,map);
    }

    /**
     * 保存/编辑 会员卡信息
     * @param merchantId 商户id
     * @param memberCard 会员卡信息
     * @param memberId 单店 会员id
     */
    private Long updateMemberCard(Long merchantId, MemberCard memberCard,Long memberId) {
        String sql = "SELECT * from member_cards where merchant_id = :merchantId and no = :no";
        QyMap param = QyMap.map("merchantId",merchantId).setv("no",memberCard.getNo());
        List<Map<String,Object>> mapList = branchJdbcTemplate.queryForList(sql,param);
        Long id = null;
        if (memberCard.getVipId()==null){
            memberId = null;
        }
        //获取单店会员卡类型信息
        List<Map<String, Object>> cardtypeList = getMemberCardType(merchantId, memberCard.getType().getUuid());
        param = QyMap.map("merchant_id",merchantId)
                .setv("amount",memberCard.getAmount())
                .setv("card_species","STOREDVALUECARD")
                .setv("deposit",memberCard.getDeposit())
                .setv("end_time",memberCard.getEndTime())
                .setv("gift_amount",memberCard.getGiftAmount())
                .setv("no",memberCard.getNo())
                .setv("password",memberCard.getPassword())
                .setv("point",memberCard.getPoint())
                .setv("start_time",memberCard.getStartTime())
                .setv("state",memberCard.getState().getKey())
                .setv("total_amount",memberCard.getTotalAmount())
                .setv("total_gift_amount",memberCard.getTotalGiftAmount())
                .setv("total_point",memberCard.getTotalPoint())
                .setv("uuid",memberCard.getUuid())
                .setv("type_id",cardtypeList.get(0).get("id"))
                .setv("batch_id",memberCard.getBatchId());

                if (memberId!=null){
                    param.setv("vip_id",memberId);
                }
                if (memberId==null && memberCard.getVipId()==null){
                    param.setv("vip_id",null);
                }

        if (CollectionUtils.isNotEmpty(mapList)){
            //编辑
            QyMap map = QyMap.WRAP(mapList.get(0));
            if (memberId==null && memberCard.getVipId()!=null){

                param.setv("vip_id",map.getLong("vip_id"));
            }
            id = map.getLong("id");
            sql = "UPDATE member_cards SET amount=:amount,card_species=:card_species,deposit=:deposit,\n" +
                    "end_time=:end_time,gift_amount=:gift_amount,no=:no,password=:password,point=:point,\n" +
                    "start_time=:start_time,state=:state,total_amount=:total_amount,total_gift_amount=:total_gift_amount,\n" +
                    "total_point=:total_point,uuid=:uuid,type_id=:type_id,vip_id=:vip_id,batch_id=:batch_id\n" +
                    "WHERE id = :id";
            param.setv("id",id);
            param.remove("merchant_id");
            branchJdbcTemplate.update(sql,param);
        }else {
            //保存
            sql = "INSERT INTO member_cards (create_at,is_deleted,status,merchant_id,amount,card_species," +
                    "deposit,end_time,gift_amount,no,password,point,start_time,state,total_amount," +
                    "total_gift_amount,total_point,uuid,type_id,vip_id,batch_id)\n" +
                    "VALUES(now(),0,0,:merchant_id,:amount,:card_species," +
                    ":deposit,:end_time,:gift_amount,:no,:password,:point,:start_time,:state,:total_amount," +
                    ":total_gift_amount,:total_point,:uuid,:type_id,:vip_id,:batch_id)";
            id = branchJdbcTemplate.insertForAutoIncrement(sql,param);
        }
        return id;
    }

    /**
     * 保存单店会员信息
     * @param
     */
    public Long updateMember(Long merchantId,Member member) {
        List<Map<String, Object>> mapList = getMembers(merchantId,member.getPhone());
        String sql;
        QyMap params = QyMap.map("merchant_id",merchantId)
                .setv("birthday",member.getBirthday())
                .setv("birthday_type",member.getBirthdayType())
                .setv("card_no",member.getCardNo())
                .setv("consume_amount",member.getConsumeAmount())
                .setv("consume_count",member.getConsumeCount())
                .setv("consume_time",member.getConsumeTime())
                .setv("gender",member.getGender().getKey())
                .setv("name",member.getName())
                .setv("phone",member.getPhone())
                .setv("source",member.getSource())
                .setv("state",member.getState().getKey());

        Long id ;
        if (CollectionUtils.isNotEmpty(mapList)){
            //编辑
            QyMap map = QyMap.WRAP(mapList.get(0));
            id = map.getLong("id");
            sql = "UPDATE members SET birthday=:birthday,birthday_type=:birthday_type,card_no=:card_no,\n" +
                    "consume_amount=:consume_amount,consume_count=:consume_count,consume_time=:consume_time,\n" +
                    "gender=:gender,name=:name,source=:source,state=:state,phone=:phone\n" +
                    "WHERE id = :id";
            params.remove("merchant_id");
            params.setv("id",map.getLong("id"));
            branchJdbcTemplate.update(sql,params);

        }else {
            //添加
            params .setv("uuid",member.getUuid());
            sql = "INSERT INTO members (create_at,is_deleted,status,merchant_id,birthday,birthday_type,card_no,consume_amount,consume_count,consume_time,gender,name,phone,source,state,uuid)\n" +
                    "VALUES(now(),0,0,:merchant_id,:birthday,:birthday_type,:card_no,:consume_amount,:consume_count,:consume_time,:gender,:name,:phone,:source,:state,:uuid)";
            id = branchJdbcTemplate.insertForAutoIncrement(sql,params);
        }
        return id;

    }

    /**
     * 根据手机号获取会员信息
     * @param merchantId
     * @param phone
     * @return
     */
    private List<Map<String, Object>> getMembers(Long merchantId,String phone) {
        String sql = "SELECT * from members where merchant_id = :merchantId and phone = :phone";
        QyMap params = QyMap.map("merchantId",merchantId).setv("phone",phone);
        return branchJdbcTemplate.queryForList(sql,params);
    }


    /**
     * 删除会员卡
     * @param deleveryRecordId
     */
    public void deletedMemberCard(Long deleveryRecordId){
        DeliveryRecord record = deliveryRecordService.findById(deleveryRecordId);
//        Long merchantId = branchService.getMerchantIdByBranchId(record.getBranchId());
        String sql = "SELECT count(*) count from member_cards where vip_id is not null and batch_id = :batchId";
        QyMap map = QyMap.map("batchId",record.getId());
        long count = branchJdbcTemplate.queryForScalar(sql,map,Long.class);
        if (count>0){
            throw new BusinessRunTimeException("会员卡已使用，不能删除",10002);
        }
        sql = "DELETE from member_cards where batch_id = :batchId";
        branchJdbcTemplate.update(sql,map);
    }

    /**
     * 配送 保存会员卡 到单店
     * @param record
     */
    public void deliveryMemberCard(DeliveryRecord record){
        Long merchantId = branchService.getMerchantIdByBranchId(record.getBranchId());
        if (merchantId==null){
            throw new BusinessRunTimeException("商户不存在",10001);
        }

        Searchable searchable = SearchUtils.newSearchableWithMerchantFilter(record.getMerchantGroupId());
        searchable.addSearchParam("deliveryId_eq",record.getId());
        List<DeliveryDetail> detailList = deliveryDetailService.findWithSort(searchable);
        if (CollectionUtils.isEmpty(detailList)){
            throw new BusinessRunTimeException("配送卡明细为空",10001);
        }
        String sql = "";
        MemberCardType cardType = memberCardTypeService.findById(record.getCardTypeId());
        //获取单店会员卡类型信息
        List<Map<String, Object>> cardtypeList = getMemberCardType(merchantId, cardType.getUuid());
        QyMap map;
        MemberCard card = null;
        Map<String,?>[] maps = new Map[detailList.size()];
        int index = 0;
        for (DeliveryDetail detail : detailList) {
            card = memberCardService.findById(detail.getCardId());
            if (card==null){
                throw new BusinessRunTimeException("会员卡信息为空",10001);
            }
            map = QyMap.map("merchant_id",merchantId)
                    .setv("amount",card.getAmount())
                    .setv("card_species","STOREDVALUECARD")
                    .setv("deposit",card.getDeposit())
                    .setv("end_time",card.getEndTime())
                    .setv("start_time",card.getStartTime())
                    .setv("gift_amount",card.getGiftAmount())
                    .setv("no",card.getNo())
                    .setv("point",card.getPoint())
                    .setv("state",card.getState().getKey())
                    .setv("total_amount",card.getTotalAmount())
                    .setv("total_gift_amount",card.getTotalGiftAmount())
                    .setv("total_point",card.getTotalPoint())
                    .setv("type_id",cardtypeList.get(0).get("id"))
                    .setv("batch_id",record.getId())
                    .setv("make_card_type",card.getMakeCardType().getKey());
            maps[index] = map;
            index++;
        }
        sql = "INSERT INTO member_cards (create_at,is_deleted,status,merchant_id,amount,card_species,deposit,end_time," +
                "start_time,gift_amount,no,point,state,total_amount,total_gift_amount,total_point,type_id,batch_id,make_card_type)\n" +
                "VALUES(now(),0,0,:merchant_id,:amount,:card_species,:deposit,:end_time," +
                ":start_time,:gift_amount,:no,:point,:state,:total_amount,:total_gift_amount,:total_point,:type_id,:batch_id,:make_card_type)";
        branchJdbcTemplate.batchUpdate(sql,maps);
    }

    /**
     * 获取单店会员卡类型信息
     * @param merchantId  商户
     * @param uuid 会员卡类型uuid
     * @return
     */
    private List<Map<String, Object>> getMemberCardType(Long merchantId, String uuid) {
        String sql;
        sql = "SELECT * from member_card_types where merchant_id = :merchantId and uuid = :uuid";
        QyMap map = QyMap.map("merchantId",merchantId).setv("uuid",uuid);
        List<Map<String,Object>> cardtypeList = branchJdbcTemplate.queryForList(sql,map);
        if (CollectionUtils.isEmpty(cardtypeList)){
            throw new BusinessRunTimeException("单店会员卡类型不存在",10002);
        }
        return cardtypeList;
    }


    /**
     * 会员卡类型 数据下发
     * @param merchantIds 商户ids
     * @param merchantGroupId
     * @param cardType 会员卡类型
     */
    public void updateMemberCardTypes(List<Long> merchantIds, Long merchantGroupId, MemberCardType cardType,List<RechargeRule> ruleList) {
        if (CollectionUtils.isEmpty(merchantIds)){
            return ;
        }
        String sql = "";
        QyMap params = null;
        List<Map<String,Object>> mapList ;
        Long id ;
        QyMap map ;
        DiscountPlan plan = null;
        //折扣方案查询单店版
        Long planId = null;
        for (Long merchantId : merchantIds) {
            planId = null;
            //查询单店 该会员卡类型是否存在
            sql="SELECT * from member_card_types where merchant_id = :merchantId and uuid = :uuid";
            params = QyMap.map("merchantId",merchantId).setv("uuid",cardType.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,params);

            //折扣方案不存在 下发折扣方案
            if (cardType.getDiscountId()!=null){
                plan = discountPlanService.findById(cardType.getDiscountId());
                if (plan!=null){
                    editDiscountPlan(merchantGroupId,merchantId,plan);
                    planId = findDiscountPlanByUUid(plan.getUuid(),merchantId);
                }else{
                    throw new BusinessRunTimeException("折扣方案不存在",10001);
                }
            }
            //查找单店的折扣方案id
            params = QyMap.map("is_deleted",cardType.isDeleted())
                    .setv("discount_id",planId)
                    .setv("merchant_id",merchantId)
                    .setv("consume_price",cardType.getConsumePrice())
                    .setv("gift_point",cardType.getGiftPoint())
                    .setv("has_consume_recharge",cardType.getHasConsumeRecharge())
                    .setv("has_vip_price",cardType.getHasVipPrice())
                    .setv("name",cardType.getName())
                    .setv("period_type",PeriodType.LONGTIME.getKey())
                    .setv("recharge_rule",cardType.getRechargeRule())
                    .setv("recharge_type",cardType.getRechargeType().getKey())
                    .setv("uuid",cardType.getUuid())
                    .setv("update_timestamp",cardType.getUpdateTimestamp())
                    .setv("pointRule",cardType.getPointRule())
                    .setv("hasUseRule",cardType.getHasUseRule())
                    .setv("useRuleDetail",cardType.getUseRuleDetail());
            if (CollectionUtils.isEmpty(mapList)){
                //不存在 添加
                sql = "INSERT INTO member_card_types (create_at,is_deleted,status,merchant_id,consume_price,gift_point," +
                        "has_consume_recharge,has_vip_price,name,period_type," +
                        "recharge_rule,recharge_type,uuid,update_timestamp,discount_id,point_rule,has_use_rule,use_rule_detail)\n" +
                        "VALUES(now(),:is_deleted,0,:merchant_id,:consume_price,:gift_point," +
                        ":has_consume_recharge,:has_vip_price,:name,:period_type," +
                        ":recharge_rule,:recharge_type,:uuid,:update_timestamp,:discount_id,:pointRule,:hasUseRule,:useRuleDetail)";
               id = branchJdbcTemplate.insertForAutoIncrement(sql,params);
                //积分规则
                if (cardType.getRechargeRule()){
                    if (CollectionUtils.isNotEmpty(ruleList)) {
                        saveRechargeRules(merchantId,id,cardType,ruleList);
                    }
                }
            }else {
                //存在 编辑
                map = QyMap.WRAP(mapList.get(0));
                id = map.getLong("id");
                if (!cardType.getUpdateTimestamp().toString().equals(map.getString("update_timestamp"))){
                    sql = "UPDATE member_card_types SET is_deleted=:is_deleted,consume_price=:consume_price,\n" +
                            "gift_point=:gift_point,has_consume_recharge=:has_consume_recharge,has_vip_price=:has_vip_price,\n" +
                            "name=:name,recharge_rule=:recharge_rule,recharge_type=:recharge_type,update_timestamp=:update_timestamp," +
                            "discount_id=:discount_id,point_rule=:pointRule,has_use_rule=:hasUseRule,use_rule_detail=:useRuleDetail  " +
                            "WHERE merchant_id = :merchant_id AND uuid=:uuid\n";
                    params.remove("period_type");
                    branchJdbcTemplate.update(sql,params);

                    //删除积分规则
                    sql = "DELETE from recharge_rules where category_id = :category_id";
                    params = QyMap.map("category_id",id);
                    branchJdbcTemplate.update(sql,params);

                    //积分规则
                    if (cardType.getRechargeRule()){
                        if (CollectionUtils.isNotEmpty(ruleList)) {
                            saveRechargeRules(merchantId,id,cardType,ruleList);
                        }
                    }
                }

            }
        }
    }

    /**
     * 根据商户 和 uuid 查询折扣方案
     * @param uuid
     * @param merchantId
     * @return
     */
    private Long findDiscountPlanByUUid(String uuid, Long merchantId) {
        String sql = "SELECT id from discount_plans where merchant_id = :merchant_id and uuid = :uuid";
        QyMap map = QyMap.map("merchant_id",merchantId).setv("uuid",uuid);
        Long id = branchJdbcTemplate.queryForScalar(sql,map,Long.class);
        return id;
    }

    /**
     * 保存积分规则
     * @param merchantId
     * @param id 单店会员卡类型id
     * @param cardType 连锁 会员卡信息
     */
    private void saveRechargeRules(Long merchantId, Long id, MemberCardType cardType,List<RechargeRule> ruleList) {
        //积分规则信息
        Map<String,?>[] maps = new Map[ruleList.size()];
        QyMap params;
        RechargeRule rule ;
        for (int i = 0; i < ruleList.size(); i++) {
            rule = ruleList.get(i);
            params = QyMap.map("merchant_id",merchantId)
                    .setv("gift_money",rule.getGiftMoney())
                    .setv("gift_point",rule.getGiftPoint())
                    .setv("range_end",rule.getRangeEnd())
                    .setv("range_start",rule.getRangeStart())
                    .setv("type",rule.getType().getKey())
                    .setv("category_id",id);
            maps[i] = params;
        }

        String sql = "INSERT into recharge_rules (create_at,is_deleted,status,merchant_id,gift_money,gift_point,range_end,range_start,type,category_id)\n" +
                "VALUES(now(),0,0,:merchant_id,:gift_money,:gift_point,:range_end,:range_start,:type,:category_id) ";
        branchJdbcTemplate.batchUpdate(sql,maps);

    }

    /**
     * 总部删除原因备注 并删除分店的对应原因备注
     * @param comment
     */
    public void deletedBranchCommentData(Comment comment) {
        String sql = "DELETE from comments where uuid = :uuid";
        QyMap map = QyMap.map("uuid",comment.getUuid());
        branchJdbcTemplate.update(sql,map);
    }

    /**
     * 总部删除支付方式 并删除分店的支付方式
     * @param payment
     */
    public void deletedBranchPaymentData(Payment payment) {
        String sql = "DELETE from payment_types where uuid = :uuid";
        QyMap map = QyMap.map("uuid",payment.getUuid());
        branchJdbcTemplate.update(sql,map);
    }

    /**
     * 总部删除服务费 并逻辑删除分店的服务费
     * @param charge
     */
    public void deleteBranchChargeData(Charge charge) {
        String sql = "update charges set is_deleted = 1 where uuid = :uuid";
        QyMap map = QyMap.map("uuid",charge.getUuid());
        branchJdbcTemplate.update(sql,map);
    }

    /**
     *  折扣方案 在分店中使用数量
     * @param plan
     */
    public Long branchUseCountForDiscountPlan(DiscountPlan plan) {
        String sql = "select count(mct.id) as count from member_card_types mct \n" +
                "left join discount_plans dp on dp.id=mct.discount_id\n" +
                "where dp.uuid=:uuid ";
        QyMap map = QyMap.map("uuid",plan.getUuid());
        Long count = branchJdbcTemplate.queryForScalar(sql,map,Long.class);
        return count;
    }

    /**
     * 删除分店折扣方案
     * @param plan
     */
    public void deleteBranchDiscountPlanData(DiscountPlan plan) {
        String sql = "DELETE from discount_plans where uuid = :uuid";
        QyMap map = QyMap.map("uuid",plan.getUuid());
        branchJdbcTemplate.update(sql,map);
    }

    /**
     * 下发总部供应商
     * @param merchantId
     * @param merchantGroupId
     */
    public void releasedSuppliers(Long merchantId, Long merchantGroupId) {
        //供应商
        Searchable searchable = SearchUtils.newSearchableWidthMerchantGroupFilter(merchantGroupId);
        List<BranchSupplier> supplierList = branchSupplierService.findWithSort(searchable);
        //下发供应商
        if (CollectionUtils.isNotEmpty(supplierList)){
            releasedBranchSuppliers(supplierList,merchantId);
        }
    }

    /**
     * 修改单店总部供应商信息
     * @param supplier
     */
    public void updateBranchSuppliers(BranchSupplier supplier) {
        //修改
        String sql = "UPDATE suppliers set update_at=now(),is_deleted=:deleted, address=:address," +
                "balance_mode=:balanceMode,full_name=:fullName,linker=:linker,name=:name,no=:no," +
                "phone=:phone,remark=:remark,update_timestamp=:updateTimestamp " +
                "where uuid = :uuid and is_chain=:isChain and update_timestamp <> :updateTimestamp";
        QyMap map =  QyMap.map("uuid",supplier.getUuid());
        map.setv("updateTimestamp",supplier.getUpdateTimestamp());
        map.setv("name",supplier.getName());
        map.setv("no",supplier.getNo());
        map.setv("remark",supplier.getRemark());
        map.setv("phone",supplier.getPhone());
        map.setv("linker",supplier.getLinker());
        map.setv("fullName",supplier.getName());
        map.setv("balanceMode",supplier.getSellType().getKey());
        map.setv("address",supplier.getAddress());
        map.setv("isChain",true);
        map.setv("deleted",supplier.isDeleted());
        branchJdbcTemplate.update(sql,map);
    }


    public enum PeriodType {
        LONGTIME("长期有效"),
        RELATIVE("相对有效"),
        FIXED("固定有效");
        private final String text;

        public String getKey() {
            return this.toString();
        }

        private PeriodType(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }
    }


    /**
     * 门店数据下发 [仓库][供应商][物料单位][物料类别][物料][物料采购规格][成本卡][成本卡明细]
     * @param bIDs 门店ids
     * @param merchantGroupId 连锁商户id
     * @param firstReleased 是否是第一次下发的门店商户ids
     */
    public void releasedBranchData(List<Long> bIDs,Long merchantGroupId,List<Long> firstReleased){
        if(CollectionUtils.isEmpty(bIDs)){
            throw new BusinessRunTimeException("数据为空",10001);
        }
        //1.将分店id 转换成merchantIds
        Set<Long> merchantIDs = changeMerchants(bIDs);
        if(CollectionUtils.isEmpty(merchantIDs)){
            throw new BusinessRunTimeException("分店商户id 为空",10001);
        }

        //第一次下发的门店需先删除门店原来的 物料 物料类别 物料单位 物料规格 成本卡 成本卡明细
        if (CollectionUtils.isNotEmpty(firstReleased)){
            deletedBranchMaterialData(firstReleased);
        }

        List<String> clearRedisKeys = null;

        //数据准备 删除状态不过滤
        Searchable searchable = SearchUtils.newSearchableWidthMerchantGroupFilter(merchantGroupId);
        //仓库
        List<BranchWarehouse> warehouseList = branchWarehouseService.findWithSort(searchable);
        //供应商
        List<BranchSupplier> supplierList = branchSupplierService.findWithSort(searchable);
        //物料单位
        List<MaterialUnit> materialUnitList = materialUnitService.findWithSort(searchable);
        //物料类别 树形 （目前只有两级）
        List<MaterialCategory> materialCategoryList = materialCategoryService.getBuildTree(merchantGroupId,false);
        //物料
        List<Material> materialList = materialService.findWithSort(searchable);
        //物料采购规格
        List<MaterialCost> materialCostList = materialCostService.findWithSort(searchable);

        //循环下发分店数据
        for (Long merchantID : merchantIDs) {
            clearRedisKeys = Lists.newArrayList();
            //下发仓库
            if(CollectionUtils.isNotEmpty(warehouseList)){
                //下发仓库信息
                releasedBranchWarehouses(warehouseList,merchantID,merchantGroupId);
                clearRedisKeys.add(RedisKeyHelper.getDishesKey("warehouses",merchantID,merchantGroupId));
            }
            //下发供应商
            if (CollectionUtils.isNotEmpty(supplierList)){
                releasedBranchSuppliers(supplierList,merchantID);
            }
            //下发物料单位
            if(CollectionUtils.isNotEmpty(materialUnitList)){
                releasedBranchMaterialUnits(materialUnitList,merchantID);
            }
            //下发物料类别
            if(CollectionUtils.isNotEmpty(materialCategoryList)){
                releasedBranchMaterialCategorys(materialCategoryList,merchantID,merchantGroupId, "0/",0L);
                clearRedisKeys.add(RedisKeyHelper.getDishesKey("material_categorys",merchantID,merchantGroupId));
            }
            //下发物料 及 物料规格
            if (CollectionUtils.isNotEmpty(materialList)){
                releasedBranchMaterials(materialList,merchantID,merchantGroupId);
                clearRedisKeys.add(RedisKeyHelper.getDishesKey("materials",merchantID,merchantGroupId));
                clearRedisKeys.add(RedisKeyHelper.getDishesKey("purchase_specs",merchantID,merchantGroupId));
            }
            //成本卡
            if(CollectionUtils.isNotEmpty(materialCostList)){
                releasedBranchMaterialCosts(materialCostList,merchantID,merchantGroupId);
            }
            redisTemplate.delete(clearRedisKeys);
        }

        //连锁表 分店第一次下发数据的字段更新为true
        if(CollectionUtils.isNotEmpty(firstReleased)){
            updateZongBuBranchFirstReleased(firstReleased);
        }

    }

    /**
     * 连锁表 分店第一次下发数据的字段更新为true
     * @param firstReleased 商户id
     */
    private void updateZongBuBranchFirstReleased(List<Long> firstReleased) {
        String sql = "UPDATE branchs set is_released = true where merchant_id in (:merchantIds) ";
        QyMap map = QyMap.map("merchantIds",firstReleased);
        jdbcTemplate.update(sql,map);
    }

    /**
     * 第一次下发数据 删除门店 物料 物料类别 物料单位 物料规格 成本卡 成本卡明细
     * @param firstReleased 商戶id
     */
    private void deletedBranchMaterialData(List<Long> firstReleased) {
//      -- 物料单位";
        String sql = "DELETE from material_units where merchant_id in(:merchantIds)";
        QyMap map = QyMap.map("merchantIds",firstReleased);
        branchJdbcTemplate.update(sql,map);
//      -- 物料类别";
        sql = "UPDATE material_categorys set is_deleted = 1 where merchant_id in(:merchantIds)";
        branchJdbcTemplate.update(sql,map);
//      -- 物料";
        sql = "update materials set is_deleted = 1 where merchant_id in(:merchantIds)";
        branchJdbcTemplate.update(sql,map);
//      -- 物料规格";
        sql = "DELETE from purchase_specs where merchant_id in (:merchantIds)";
        branchJdbcTemplate.update(sql,map);
//      -- 成本卡明细";
        sql = "DELETE from material_cost_details where merchant_id in(:merchantIds) ";
        branchJdbcTemplate.update(sql,map);
//      -- 成本卡";
        sql = "DELETE from material_costs where merchant_id in(:merchantIds) ";
        branchJdbcTemplate.update(sql,map);
    }

    /**
     * 下发成本卡 及 成本卡明细
     * @param materialCostList  连锁成本卡
     * @param merchantID
     * @param merchantGroupId
     */
    private void releasedBranchMaterialCosts(List<MaterialCost> materialCostList,Long merchantID,Long merchantGroupId){
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        String redisKey = "";
        BoundHashOperations<String, String, String> hashOperations;
        Dishes dishes = null;
        DishesSpecification specification = null;
        //查询门店对应存在uuid的菜品
        sql = "SELECT merchant_id,uuid,id from dishess where merchant_id = :merchantId and uuid is not null ";
        map = QyMap.map("merchantId",merchantID);
        mapList = branchJdbcTemplate.queryForList(sql,map);
        Map<Long, Set<String>> branchDataMap = null;
        Map<String,Long> dishesMap = null;
        if(CollectionUtils.isNotEmpty(mapList)){
            branchDataMap = mapList.stream()
                    .map(QyMap::new)
                    .filter(x->x.get("uuid")!=null)
                    .collect(Collectors.groupingBy(x->x.getLong("merchant_id"), Collectors.mapping(x->x.getString("uuid"), Collectors.toSet())));

           dishesMap = mapList.stream().map(QyMap::new)
                    .filter(x->x.get("uuid")!=null)
                    .collect(Collectors.toMap(x->x.getString("uuid"),x->x.getLong("id")));
        }

        //查詢門店對應存在uuid 的 菜品規格
        sql = "SELECT merchant_id,uuid,id from dishes_specifications where merchant_id = :merchantId and uuid is not null";
        mapList = branchJdbcTemplate.queryForList(sql,map);
        Map<String,Long> dishesSpecMap = null;
        if(CollectionUtils.isNotEmpty(mapList)){
            // uuid --> id
            dishesSpecMap = mapList.stream().map(QyMap::new)
                    .filter(x->x.get("uuid")!=null)
                    .collect(Collectors.toMap(x->x.getString("uuid"),x->x.getLong("id")));
        }

        Set<String> stringSet = null;
        for (MaterialCost cost : materialCostList) {
            dishes = dishesService.findById(cost.getDishesId());
            if(dishes==null){
                throw new BusinessRunTimeException("菜品信息不存在",1001);
            }
            if(MapUtils.isNotEmpty(branchDataMap)){
                stringSet = branchDataMap.get(merchantID);
            }else {
                stringSet = new HashSet<>();
            }
//            5.判断成本卡对应菜品uuid是否在单店系统菜品uuid 中存在
            if(CollectionUtils.isNotEmpty(stringSet) && stringSet.contains(dishes.getUuid())){
                //存在 就下发成本卡
                sql = "SELECT * from material_costs where merchant_id = :merchantId and uuid = :uuid ";
                map =  QyMap.map("merchantId",merchantID).setv("uuid",cost.getUuid());
                mapList = branchJdbcTemplate.queryForList(sql,map);
                map =  QyMap.map("merchantId",merchantID);
                map.setv("uuid",cost.getUuid());
                map.setv("updateTimestamp",cost.getUpdateTimestamp());
                map.setv("deleted",cost.isDeleted());
                map.setv("cost",cost.getCost());
                map.setv("dishesId",dishesMap.get(dishes.getUuid()));
                map.setv("materialCost",cost.getMaterialCost());
                map.setv("otherCost",cost.getOtherCost());
                map.setv("processQty",cost.getProcessQty());
                map.setv("remark",cost.getRemark());
                if(cost.getSpecId()!=null){
                    specification = dishesSpecificationService.findById(cost.getSpecId());
                    map.setv("specId",dishesSpecMap.get(specification.getUuid()));
                }else {
                    map.setv("specId",null);
                }
//                redisKey = RedisKeyHelper.getDishesKey("warehouses",merchantID,merchantGroupId);
//                hashOperations = redisTemplate.boundHashOps(redisKey);
//                map.setv("warehouseId",hashOperations.get(cost.getWarehouseId().toString()));
                if(CollectionUtils.isEmpty(mapList)){
                    //添加
                    sql = "INSERT INTO material_costs(create_at,is_deleted,status,merchant_id,cost,dishes_id,material_cost,other_cost," +
                            "process_qty,remark,spec_id,uuid,update_timestamp) " +
                            "VALUES(now(),:deleted,0,:merchantId,:cost,:dishesId,:materialCost,:otherCost," +
                            ":processQty,:remark,:specId,:uuid,:updateTimestamp)";
                   cid =  branchJdbcTemplate.insertForAutoIncrement(sql,map);
                }else{
                    maps = mapList.get(0);
                    qyMap = QyMap.WRAP(maps);
                    cid = qyMap.getLong("id");
                    if(!qyMap.getString("update_timestamp").equals(cost.getUpdateTimestamp().toString())){

                        //修改
                        sql = "update material_costs set update_at = now(),is_deleted=:deleted,cost=:cost,dishes_id=:dishesId," +
                                "material_cost=:materialCost,other_cost=:otherCost,process_qty=:processQty,remark=:remark,spec_id=:specId," +
                                "update_timestamp=:updateTimestamp " +
                                "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                        branchJdbcTemplate.update(sql,map);

                    }
                }
                //删除成本卡明细
                deletedBranchMaterialCostDetail(cid);
                //添加成本卡明细
                insertMaterialCostDetails(cid,cost.getId(),merchantGroupId,merchantID);

            }


            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
//            saveRedis(merchantGroupId,merchantID,spec.getId(),cid,"purchase_specs");
        }
    }

    /**
     * 添加成本卡明细
     * @param cid 单店 成本卡id
     * @param id 连锁成本卡id
     * @param merchantGroupId
     * @param merchantID
     */
    private void insertMaterialCostDetails(Long cid, Long id, Long merchantGroupId, Long merchantID) {
        String sql = "";
        Searchable searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
        searchable.addSearchParam("cost.id_eq",id);
        List<MaterialCostDetail> detailList = materialCostDetailService.findWithSort(searchable);
        QyMap map ;
        String redisKey = "";
        BoundHashOperations<String, String, String> hashOperations;
        if(CollectionUtils.isNotEmpty(detailList)){
            for (MaterialCostDetail detail : detailList) {
                //添加成本卡明细
                sql = "INSERT INTO material_cost_details(create_at,is_deleted,status,merchant_id,expend,new_total,principal,remark,total,cost_id,material_id)\n" +
                        " VALUES(now(),:deleted,0,:merchantId,:expend,:newTotal,:principal,:remark,:total,:costId,:materialId)";
                map = QyMap.map("deleted",detail.isDeleted())
                        .setv("merchantId",merchantID)
                        .setv("expend",detail.getExpend())
                        .setv("newTotal",0)
                        .setv("principal",detail.getPrincipal())
                        .setv("remark",detail.getRemark())
                        .setv("total",0)
                        .setv("costId",cid);
                redisKey = RedisKeyHelper.getDishesKey("materials",merchantID,merchantGroupId);
                hashOperations = redisTemplate.boundHashOps(redisKey);
                map.setv("materialId",hashOperations.get(detail.getMaterialId().toString()));
                branchJdbcTemplate.update(sql,map);
            }
        }

    }

    /**
     * 删除成本卡明细
     * @param cid 成本卡id
     */
    private void deletedBranchMaterialCostDetail(Long cid) {
        String sql = "DELETE from material_cost_details WHERE cost_id = :costId ";
        QyMap map = QyMap.map("costId",cid);
        branchJdbcTemplate.update(sql,map);
    }

    /**
     * 下发物料
     * @param materialList
     * @param merchantID
     */
    private void releasedBranchMaterials(List<Material> materialList,Long merchantID,Long merchantGroupId){
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        String redisKey = "";
        BoundHashOperations<String, String, String> hashOperations;
        List<PurchaseSpec> specList ;
        Searchable searchable = null;
        for (Material material : materialList) {
            sql = "SELECT * from materials where merchant_id = :merchantId and uuid = :uuid ";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",material.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);
            map =  QyMap.map("merchantId",merchantID);
            map.setv("uuid",material.getUuid());
            map.setv("updateTimestamp",material.getUpdateTimestamp());
            map.setv("name",material.getName());
            map.setv("state",material.getState().getKey());
            map.setv("no",material.getNo());
            map.setv("pinyin",material.getPinyin());
            map.setv("spell",material.getSpell());
            redisKey = RedisKeyHelper.getDishesKey("material_categorys",merchantID,merchantGroupId);
            hashOperations = redisTemplate.boundHashOps(redisKey);
            map.setv("category_id",hashOperations.get(material.getCategory().getId().toString()));
            map.setv("goods_spec",material.getGoodsSpec());
            map.setv("unit",material.getUnit());
            map.setv("min_stock",material.getMinStock());
            map.setv("max_stock",material.getMaxStock());
            map.setv("store_mode",material.getStoreMode()!=null?material.getStoreMode().getKey():null);
            map.setv("purchase_new_price",material.getPurchaseNewPrice());
            map.setv("consume_unit",material.getConsumeUnit());
            map.setv("consume_rates",material.getConsumeRates());
            map.setv("order_price_bom",material.getOrderPriceBom());
            map.setv("order_type",material.getOrderType()!=null?material.getOrderType().getKey():null);
            map.setv("stocktake_type",material.getStocktakeType()!=null?material.getStocktakeType().getKey():null);
            map.setv("deleted",material.isDeleted());
            map.setv("materialType",material.getMaterialType().getKey());
            map.setv("hasRelation",material.getHasRelation());
            map.setv("code",material.getCode());
            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT INTO materials(create_at,is_deleted,status,merchant_id,no,name,pinyin,spell,category_id," +
                        "goods_spec,unit,min_stock,max_stock,store_mode,purchase_new_price,consume_unit,consume_rates," +
                        "order_price_bom,order_type,stocktake_type,state,uuid,update_timestamp,material_type,has_relation,code)\n" +
                        "VALUES(now(),:deleted,0,:merchantId,:no,:name,:pinyin,:spell,:category_id," +
                        ":goods_spec,:unit,:min_stock,:max_stock,:store_mode,:purchase_new_price,:consume_unit,:consume_rates," +
                        ":order_price_bom,:order_type,:stocktake_type,:state,:uuid,:updateTimestamp,:materialType,:hasRelation,:code)\n";
                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
//                if(!qyMap.getString("update_timestamp").equals(material.getUpdateTimestamp().toString())){
                    //修改
                    log.info(">>>>>>>>>>>>>>>>>>>>>>>>0------- map : {}",map);
                    sql = "UPDATE materials set update_at=NOW(),is_deleted=:deleted,no=:no,name=:name,pinyin=:pinyin,spell=:spell,category_id=:category_id," +
                            "goods_spec=:goods_spec,unit=:unit,min_stock=:min_stock,store_mode=:store_mode,purchase_new_price=:purchase_new_price, " +
                            "consume_unit=:consume_unit,consume_rates=:consume_rates,order_price_bom=:order_price_bom,order_type=:order_type," +
                            "stocktake_type=:stocktake_type,state=:state,update_timestamp=:updateTimestamp,material_type=:materialType,has_relation=:hasRelation,code=:code " +
                            "where merchant_id= :merchantId and uuid = :uuid";
                    branchJdbcTemplate.update(sql,map);

//                }
                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }


            log.info("materialId :::::::  ----- :{}",material.getId());

            saveRedis(merchantGroupId,merchantID,material.getId(),cid,"materials");
            //删除物料规格
            deletedBranchMaterialSpecs(cid);

            //添加物料规格
            searchable = SearchUtils.newSearchableWidthMerchantGroupFilter(merchantGroupId);
            searchable.addSearchParam("material.id_eq",material.getId());
            specList = purchaseSpecService.findWithSort(searchable);
            if(CollectionUtils.isNotEmpty(specList)){
                //添加物料规格
                insertMaterialSpec(specList,cid,merchantID,merchantGroupId);
            }
        }

        for (Material material : materialList) {
            //下发加工关系 成品 和 有加工关系
            if(material.getMaterialType()== MaterialType.PRODUCT && material.getHasRelation()){
                releaseMachiningRelation(material,merchantGroupId,merchantID);
            }
        }

    }

    /**
     * 下发加工关系
     * @param material
     * @param merchantGroupId
     * @param merchantID
     * @param
     */
    private void releaseMachiningRelation(Material material, Long merchantGroupId, Long merchantID) {
        //查询加工关系是否有
        String redisKey = "";
        BoundHashOperations<String, String, String> hashOperations;
        String sql = "SELECT * from machining_relations where product_id = :productId";
        redisKey = RedisKeyHelper.getDishesKey("materials",merchantID,merchantGroupId);
        hashOperations = redisTemplate.boundHashOps(redisKey);
        QyMap params = QyMap.map("productId",hashOperations.get(material.getId().toString()));
        List<Map<String,Object>> list = branchJdbcTemplate.queryForList(sql,params);
        if (CollectionUtils.isNotEmpty(list)){
            //删除加工关系
            sql = "DELETE FROM machining_relations WHERE product_id=:productId";
            branchJdbcTemplate.update(sql,params);
        }

        //查询成品原料对应的加工关系
        Searchable searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
        searchable.addSearchFilter("productId",SearchOperator.eq,material.getId());
        List<MachiningRelation> relationList = machiningRelationService.findWithSort(searchable);
        if(CollectionUtils.isEmpty(relationList)){
            return;
        }

        Map<String,?>[] maps = new Map[relationList.size()];
        int index = 0;
        for (MachiningRelation relation : relationList) {
            //建立加工关系
            params = QyMap.map("merchant_id",merchantID)
                    .setv("count",relation.getCount());
            redisKey = RedisKeyHelper.getDishesKey("materials",merchantID,merchantGroupId);
            hashOperations = redisTemplate.boundHashOps(redisKey);
                    params.setv("material_id",hashOperations.get(relation.getMaterialId().toString()));
                    params.setv("product_id",hashOperations.get(material.getId().toString()))
                            .setv("remark",relation.getRemark());
            maps[index] = params;
            index++;

        }
        sql = "INSERT INTO machining_relations (create_at,is_deleted,status,merchant_id,count,material_id,product_id,remark)\n" +
                "VALUES(now(),0,0,:merchant_id,:count,:material_id,:product_id,:remark)";
        branchJdbcTemplate.batchUpdate(sql,maps);

    }

    /**
     * 添加物料规格
     * @param specList 规格信息
     * @param cid 分店物料id
     * @param merchantID
     */
    private void insertMaterialSpec(List<PurchaseSpec> specList,Long cid, Long merchantID,Long merchantGroupId) {
        QyMap map;
        String sql = "";
        Long id = null;
        for (PurchaseSpec spec : specList) {
            sql = "INSERT INTO purchase_specs(create_at,is_deleted,status,merchant_id,name,price,range1,unit,material_id,has_def) " +
                    " VALUES(now(),:deleted,0,:merchantId,:name,:price,:range1,:unit,:material_id,:has_def) ";
            map =  QyMap.map("merchantId",merchantID);
            map.setv("name",spec.getName());
            map.setv("price",spec.getPrice());
            map.setv("range1",spec.getRatio());
            map.setv("material_id",cid);
            map.setv("unit",spec.getUnit());
            map.setv("deleted",spec.isDeleted());
            map.setv("has_def",spec.getHasDef());
            id = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
            saveRedis(merchantGroupId,merchantID,spec.getId(),id,"purchase_specs");
        }
    }

    /**
     * 删除物料规格信息
     * @param id 物料id
     */
    private void deletedBranchMaterialSpecs(long id) {
        String sql = "DELETE from purchase_specs where material_id = :materialId ";
        QyMap map = QyMap.map("materialId",id);
        branchJdbcTemplate.update(sql,map);
    }


    /**
     * 下发物料类别
     * @param materialCategoryList
     * @param merchantID
     */
    private void releasedBranchMaterialCategorys(List<MaterialCategory> materialCategoryList,Long merchantID,Long merchantGroupId, String parentIds,Long parentId){
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        for (MaterialCategory category : materialCategoryList) {
            sql = "SELECT * from material_categorys where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",category.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);
            map =  QyMap.map("merchantId",merchantID);
            map.setv("uuid",category.getUuid());
            map.setv("updateTimestamp",category.getUpdateTimestamp());
            map.setv("name",category.getName());
            map.setv("no",category.getNo());
            map.setv("weight",category.getWeight());
            map.setv("parentIds",parentIds);
            map.setv("parentId",parentId);//0
            map.setv("deleted",category.isDeleted());//0
            map.setv("dishes_category_id",category.getDishesCategoryId());
            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT INTO material_categorys(create_at,is_deleted,status,has_children,name,parent_id,parent_ids,is_show,weight,merchant_id,no,uuid,update_timestamp,dishes_category_id) " +
                        "VALUES(now(),:deleted,0,0,:name,:parentId,:parentIds,1,:weight,:merchantId,:no,:uuid,:updateTimestamp,:dishes_category_id)";
                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(!qyMap.getString("update_timestamp").equals(category.getUpdateTimestamp().toString())){
                    //修改
                    sql = "UPDATE material_categorys SET is_deleted=:deleted,name=:name,parent_id= :parentId,parent_ids=:parentIds,weight=:weight,no=:no,update_timestamp=:updateTimestamp,dishes_category_id=:dishes_category_id " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
            saveRedis(merchantGroupId,merchantID,category.getId(),cid,"material_categorys");
            //子集
            if(CollectionUtils.isNotEmpty(category.getChildren())){
                releasedBranchMaterialCategorys(category.getChildren(),merchantID,merchantGroupId, parentIds+cid+"/",cid);
            }
        }


    }


    /**
     * 下发物料单位
     * @param materialUnitList 物料单位集合
     * @param merchantID
     */
    private void releasedBranchMaterialUnits(List<MaterialUnit> materialUnitList,Long merchantID){
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        for (MaterialUnit unit : materialUnitList) {
            sql = "SELECT * from material_units where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",unit.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);

            map =  QyMap.map("merchantId",merchantID);
            map.setv("uuid",unit.getUuid());
            map.setv("updateTimestamp",unit.getUpdateTimestamp());
            map.setv("name",unit.getName());
            map.setv("state",unit.getState().getKey());
            map.setv("no",unit.getNo());
            map.setv("remark",unit.getRemark());
            map.setv("nameEn",unit.getNameEn());
            map.setv("deleted",unit.isDeleted());
            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT INTO material_units(create_at,is_deleted,status,merchant_id,name,name_en,no,remark,state,uuid,update_timestamp) " +
                        "VALUES(now(),:deleted,0,:merchantId,:name,:nameEn,:no,:remark,:state,:uuid,:updateTimestamp)";
                branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(!qyMap.getString("update_timestamp").equals(unit.getUpdateTimestamp().toString())){
                    //修改
                    sql = "UPDATE material_units SET update_at=now(),is_deleted=:deleted,name=:name,name_en=:nameEn,no=:no,remark=:remark,state=:state,update_timestamp=:updateTimestamp " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
//                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
        }
    }


    /**
     * 下发供应商信息
     * @param supplierList
     * @param merchantID
     */
    private void releasedBranchSuppliers(List<BranchSupplier> supplierList,Long merchantID){
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        for (BranchSupplier supplier : supplierList) {
            sql = "SELECT * from suppliers where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",supplier.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);

            map =  QyMap.map("merchantId",merchantID);
            map.setv("uuid",supplier.getUuid());
            map.setv("updateTimestamp",supplier.getUpdateTimestamp());
            map.setv("name",supplier.getName());
            map.setv("state","NORMAL");
            map.setv("no",supplier.getNo());
            map.setv("remark",supplier.getRemark());
            map.setv("phone",supplier.getPhone());
            map.setv("linker",supplier.getLinker());
            map.setv("fullName",supplier.getName());
            map.setv("balanceMode",supplier.getSellType().getKey());
            map.setv("address",supplier.getAddress());
            map.setv("isChain",true);
            map.setv("deleted",supplier.isDeleted());
            map.setv("bank_name",supplier.getBankName())
                    .setv("credit_no",supplier.getCreditNo())
                    .setv("bank_no",supplier.getBankNo());
            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT INTO suppliers(create_at,is_deleted,status,merchant_id,address,balance_mode,full_name,linker,name,no,phone,remark,state,uuid,update_timestamp,is_chain,bank_name,bank_no,credit_no) " +
                        "VALUES(now(),:deleted,0,:merchantId,:address,:balanceMode,:fullName,:linker,:name,:no,:phone,:remark,:state,:uuid,:updateTimestamp,:isChain,:bank_name,:bank_no,:credit_no)";
                 branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(!qyMap.getString("update_timestamp").equals(supplier.getUpdateTimestamp().toString())){
                    //修改
                    sql = "UPDATE suppliers set update_at=now(),is_deleted=:deleted, address=:address,balance_mode=:balanceMode,full_name=:fullName,linker=:linker,name=:name,no=:no,phone=:phone,remark=:remark,state=:state,update_timestamp=:updateTimestamp,bank_name=:bank_name,bank_no=:bank_no,credit_no=:credit_no " +
                            "where merchant_id= :merchantId and uuid = :uuid and is_chain=:isChain and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
//                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
        }
    }

    /**
     * 下发仓库信息
     * @param warehouseList
     * @param merchantID
     */
    private void releasedBranchWarehouses(List<BranchWarehouse> warehouseList,Long merchantID,Long merchantGroupId){
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        for (BranchWarehouse warehouse : warehouseList) {
            sql = "SELECT * from warehouses where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",warehouse.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);

            map =  QyMap.map("merchantId",merchantID);
            map.setv("name",warehouse.getName());
            map.setv("state","NORMAL");
            map.setv("no",warehouse.getNo());
            map.setv("uuid",warehouse.getUuid());
            map.setv("updateTimestamp",warehouse.getUpdateTimestamp());
            map.setv("deleted",warehouse.isDeleted());
            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT INTO warehouses(create_at,is_deleted,status,merchant_id,name,no,state,uuid,update_timestamp) " +
                        "VALUES(now(),:deleted,0,:merchantId,:name,:no,:state,:uuid,:updateTimestamp)";
                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(!qyMap.getString("update_timestamp").equals(warehouse.getUpdateTimestamp().toString())){
                    //修改
                    sql = "UPDATE warehouses set update_at=now(),is_deleted=:deleted, name=:name,no=:no,state=:state,update_timestamp=:updateTimestamp " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
            saveRedis(merchantGroupId,merchantID,warehouse.getId(),cid,"warehouses");
        }
    }



    /**
     * 下发菜品变价
     * @param bIDs 分店ids
     * @param dataList 变价数据
     */
    public void updateChangePrices(List<Long> bIDs,List<ChangePrice> dataList){
        if(CollectionUtils.isEmpty(bIDs) || CollectionUtils.isEmpty(dataList)){
            throw new BusinessRunTimeException("数据为空",10001);
        }
        //1.将分店id 转换成merchantIds
        Set<Long> merchantIDs = changeMerchants(bIDs);
        if(CollectionUtils.isEmpty(merchantIDs)){
            throw new BusinessRunTimeException("分店商户id 为空",10001);
        }

        String sql = "";
        Dishes dishes = null;
        DishesSpecification specification = null;
        QyMap params = null;
        List<Map<String,Object>> mapList = null;
        QyMap map = null;
        for (Long merchantID : merchantIDs) {
            for (ChangePrice price : dataList) {
                dishes = dishesService.findById(price.getDishesId());
                if (dishes==null){
                    throw new BusinessRunTimeException("菜品信息不存在",10001);
                }
                sql = "SELECT * from dishess where merchant_id = :merchantId and uuid =:uuid";
                params = QyMap.map("merchantId",merchantID).setv("uuid",dishes.getUuid());
                mapList = branchJdbcTemplate.queryForList(sql,params);
                if (CollectionUtils.isNotEmpty(mapList)){
                    //单店菜品信息
                    map = QyMap.WRAP(mapList.get(0));
                    sql = "UPDATE dishess set update_at=now(), price = :price,vip_price = :vipPrice where id = :dishesId";
                    params = QyMap.map("dishesId",map.getLong("id"))
                            .setv("price",price.getPrice())
                            .setv("vipPrice",price.getVipPrice());
                    branchJdbcTemplate.update(sql,params);
                    //规格信息中价格修改
                    if(price.getSpecId()!=null){
                        specification = dishesSpecificationService.findById(price.getSpecId());
                        //查询单店版规格
                        sql = "SELECT * from dishes_specifications where merchant_id = :merchantId and uuid =:uuid";
                        params = QyMap.map("merchantId",merchantID).setv("uuid",specification.getUuid());
                        mapList = branchJdbcTemplate.queryForList(sql,params);
                        if(CollectionUtils.isNotEmpty(mapList)){
                            sql = "UPDATE dishes_specification_relations set update_at=now(),price = :price,vip_price = :vipPrice  where dishes_id = :dishesId and spec_id = :specId";
                            params = QyMap.map("dishesId",map.getLong("id")).setv("specId",mapList.get(0).get("id"))
                            .setv("price",price.getPrice()).setv("vipPrice",price.getVipPrice());
                            branchJdbcTemplate.update(sql,params);
                        }
                    }else {
                        //没有规格 修改规格关系
                        sql = "UPDATE dishes_specification_relations set update_at=now(), price = :price,vip_price = :vipPrice  where dishes_id = :dishesId and spec_id is null";
                        params = QyMap.map("dishesId",map.getLong("id")).setv("price",price.getPrice()).setv("vipPrice",price.getVipPrice());
                        branchJdbcTemplate.update(sql,params);
                    }
                }
            }
        }
    }

    /**
     * 下发数据 折扣方案
     * @param bIDs 分店ids
     * @param dataList 折扣方案数据
     */
    public void updateDiscountPlan(List<Long> bIDs,List<DiscountPlan> dataList,Long merchantGroupId){
        if(CollectionUtils.isEmpty(bIDs) || CollectionUtils.isEmpty(dataList)){
            throw new BusinessRunTimeException("数据为空",10001);
        }
        //1.将分店id 转换成merchantIds
        Set<Long> merchantIDs = changeMerchants(bIDs);
        if(CollectionUtils.isEmpty(merchantIDs)){
            throw new BusinessRunTimeException("分店商户id 为空",10001);
        }
        QyMap param = null;
        Long did = null; //折扣方案id
        List<Map<String,Object>> maplist = null;
        String sql = "";
        QyMap map = null;
        for (Long merchantID : merchantIDs) {
            for (DiscountPlan plan : dataList) {
                editDiscountPlan(merchantGroupId, merchantID, plan);
            }
        }

    }

    /**
     * 编辑折扣方案
     * @param merchantGroupId
     * @param merchantID
     * @param plan
     */
    private void editDiscountPlan(Long merchantGroupId, Long merchantID, DiscountPlan plan) {
        String sql;
        QyMap param;
        List<Map<String, Object>> maplist;
        QyMap map;
        Long did;
        sql = "SELECT * from discount_plans where merchant_id = :merchantId and uuid = :uuid ";
        param = QyMap.map("merchantId",merchantID).setv("uuid",plan.getUuid());
        maplist = branchJdbcTemplate.queryForList(sql,param);
        param = QyMap.NEW();
        param.setv("merchantId",merchantID);
        param.setv("updateTimestamp",plan.getUpdateTimestamp());
        param.setv("uuid",plan.getUuid());
        param.setv("name",plan.getName());
        param.setv("endTime",plan.getEndTime());
        param.setv("startTime",plan.getStartTime());
        param.setv("state",plan.getState().getKey());
        param.setv("discount",plan.getDiscount());
        param.setv("type",plan.getType().getKey());
        param.setv("deleted",plan.isDeleted());
        param.setv("use_scene",plan.getUseScene().getKey());
        if(CollectionUtils.isNotEmpty(maplist)){
            //update
            map = QyMap.WRAP(maplist.get(0));
            did = map.getLong("id");
            if(!plan.getUpdateTimestamp().toString().equals(map.getString("update_timestamp"))){
                //删除折扣明细
                deletedDiscountDetails(map.getLong("id"));
                sql="UPDATE discount_plans set update_at=now(),is_deleted=:deleted, discount=:discount,end_time=:endTime,name=:name,start_time=:startTime,state=:state,type=:type,update_timestamp=:updateTimestamp,use_scene=:use_scene " +
                        " where merchant_id=:merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                branchJdbcTemplate.update(sql,param);
                if (plan.getType()== DiscountType.PLAN) {
                    releasedDiscountDetails(merchantID,did,plan.getId(),merchantGroupId);
                }
            }
        }else {
            //insert
            sql = "INSERT INTO discount_plans(create_at,is_deleted,status,merchant_id,discount,end_time,name,start_time,state,type,uuid,update_timestamp,use_scene)\n" +
                    "VALUES(now(),:deleted,0,:merchantId,:discount,:endTime,:name,:startTime,:state,:type,:uuid,:updateTimestamp,:use_scene)";
            did = branchJdbcTemplate.insertForAutoIncrement(sql,param);
            //折扣方案明细 方案折扣
            if (plan.getType()== DiscountType.PLAN) {
                releasedDiscountDetails(merchantID,did,plan.getId(),merchantGroupId);
            }
        }
    }

    private void deletedDiscountDetails(Long discountId){
        String sql = "DELETE from discount_details where discount_id = :discountId";
        QyMap map = QyMap.map("discountId",discountId);
        branchJdbcTemplate.update(sql,map);
    }

    /**
     * 下发折扣方案明细
     * @param merchantId
     * @param bDid 单店折扣方案id
     * @param planId 连锁折扣方案id
     * @param merchantGroupId
     */
    private void releasedDiscountDetails(Long merchantId,Long bDid,Long planId,Long merchantGroupId){
        // 查询单店版菜品 uuid 不为空的
        String sql = "SELECT * from dishess where merchant_id = :merchantId and uuid is not null";
        QyMap param = QyMap.map("merchantId",merchantId);
        List<Map<String,Object>> mapList = branchJdbcTemplate.queryForList(sql,param);

        //菜品类别
        sql = "SELECT * from dishes_categorys where uuid is not null and merchant_id = :merchantId";
        List<Map<String,Object>> cateGoryList = branchJdbcTemplate.queryForList(sql,param);
        List<String> uuids = cateGoryList.stream().map(QyMap::WRAP).map(x->x.getString("uuid")).collect(Collectors.toList());


        Searchable searchable = null;
        //连锁折扣明细
        searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
        searchable.addSearchParam("discountId_eq",planId);
        List<DiscountDetail> discountDetailList = discountDetailService.findWithSort(searchable);
        Dishes dishes = null;
        QyMap category;
        DishesCategory dishesCategory;
        if (CollectionUtils.isNotEmpty(discountDetailList)){
            for (DiscountDetail detail : discountDetailList) {
                dishes = dishesService.findById(detail.getDishesId());
                if(CollectionUtils.isNotEmpty(mapList)){
                    //菜品不为空 和本次连锁的折扣明细 比较，有的填写折扣明细
                    for (Map<String, Object> map : mapList) {
                        if (dishes!=null){
                            if (dishes.getUuid().equals(map.get("uuid").toString())){
                                //添加折扣方案
                                sql = "INSERT into discount_details(create_at,is_deleted,status,merchant_id,rate,category_id,discount_id,dishes_id)\n" +
                                        "VALUES(now(),:deleted,0,:merchantId,:rate,:categoryId,:discountId,:dishesId)";
                                param = QyMap.map("merchantId",merchantId)
                                        .setv("rate",detail.getRate())
                                        .setv("categoryId",map.get("category_id"))
                                        .setv("discountId",bDid)
                                        .setv("deleted",detail.isDeleted())
                                        .setv("dishesId",map.get("id"));
                                branchJdbcTemplate.update(sql,param);
                            }
                        }else {
                            //菜品类别 存在
                            dishesCategory = dishesCategoryService.findById(detail.getCategoryId());
                            if (dishesCategory!=null){

                                if (uuids.contains(dishesCategory.getUuid())){
                                    param = QyMap.map("merchantId",merchantId)
                                            .setv("rate",detail.getRate())
                                            .setv("categoryId",map.get("category_id"))
                                            .setv("discountId",bDid)
                                            .setv("deleted",detail.isDeleted())
                                            .setv("dishesId",null);

                                    sql = "INSERT into discount_details(create_at,is_deleted,status,merchant_id,rate,category_id,discount_id,dishes_id)\n" +
                                            "VALUES(now(),:deleted,0,:merchantId,:rate,:categoryId,:discountId,:dishesId)";
                                    branchJdbcTemplate.update(sql,param);
                                }

                            }

                        }

                    }
                }
            }
        }
    }


    /**
     * 商品原料下发
     * @param menu 商品原料下发基本信息
     * @param bIDs 分店
     * @param changeBranch 是否更改菜品库
     * @param merchantGroupId 商户组id
     * @param isNew 是否新品发布
     */
    public void releasedDishesAndMaterial(DishesMenu menu,List<Long> bIDs,Map<Long,Boolean> changeBranch,Long merchantGroupId,boolean isNew){
        if(CollectionUtils.isEmpty(bIDs)){
            throw new BusinessRunTimeException("下发门店为空",10001);
        }
        List<Long> dishesIDs = JSON.parseArray(menu.getDishesDetails(), Long.class); //菜品id
        List<Long> materialIDs = JSON.parseArray(menu.getMaterialDetails(),Long.class); //原料id

        //1.将分店id 转换成merchantIds
        Set<Long> merchantIDs = changeMerchants(bIDs);
        if(CollectionUtils.isEmpty(merchantIDs)){
            throw new BusinessRunTimeException("分店商户id 为空",10001);
        }
        //判断该店面是否更改了菜品库，如果已经更改，则删除（物理删除）所有与菜品相关数据
        List<Long> mIds = Lists.newArrayList();
        if (MapUtils.isNotEmpty(changeBranch)){
            for (Long merchantID : merchantIDs) {
                if(changeBranch.get(merchantID)){
                    mIds.add(merchantID);
                }
            }
            //物理删除 所有与菜品相关的数据
            if(CollectionUtils.isNotEmpty(mIds)){
                deleteDishes(mIds);
            }
        }


        List<DishesCategory> categoryList = null;
        List<DishesSpecification> specificationList = null;
        List<DishesMakeCategory> makeCategoryList = null;
        List<DishesFeedCategory> feedCategoryList = null;
        List<DishesUnit> unitList = null;
        List<DishesMake> makeList = null;
        List<DishesFeed> feedList = null;
        List<Dishes> dishes = null;
        Searchable searchable = null;
        //单位
        searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
        searchable.addSearchParam("storeId_eq",menu.getStoreId());
        unitList = dishesUnitService.findWithSort(searchable);

        //商品扩展字段
        List<DishesExtend> extendList = dishesExtendService.findWithSort(searchable);

        List<MaterialCost> materialCostList = null;
        List<Brand> brandList = null;
        if(menu.getCostCard()){
            //成本卡
//            searchable.addSearchParam("storeId_eq",menu.getStoreId());
            searchable.addSearchFilter("dishesId",SearchOperator.in,dishesIDs);
            materialCostList = materialCostService.findWithSort(searchable);
            if (CollectionUtils.isNotEmpty(materialCostList)){
                //成本卡id
                List<Long> cids = materialCostList.stream().map(x->x.getId()).collect(Collectors.toList());
                //菜品id
                List<Long> deids = materialCostList.stream().map(x->x.getDishesId()).collect(Collectors.toList());
                searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
                searchable.addSearchParam("cost.id_in",cids);
                List<MaterialCostDetail> costDetails = materialCostDetailService.findWithSort(searchable);
                List<Long> maids = costDetails.stream().map(x->x.getMaterialId()).collect(Collectors.toList());
                if(CollectionUtils.isEmpty(dishesIDs)){
                    dishesIDs = Lists.newArrayList();
                }
                dishesIDs.addAll(deids);
                log.info("maids :: {}",maids);
                log.info("materialIDs 111  :: {}",materialIDs);
                if(CollectionUtils.isEmpty(materialIDs)){
                    materialIDs = Lists.newArrayList();
                }
                materialIDs.addAll(maids);
                log.info("materialIDs 222  :: {}",materialIDs);
            }
        }



        //查询菜品 下发菜品信息
        if(CollectionUtils.isNotEmpty(dishesIDs)){
            dishesIDs = dishesIDs.stream().distinct().collect(Collectors.toList());
            dishes = dishesRepository.findAllById(dishesIDs);
            //下发菜品库 将所有总部下发菜品信息逻辑删除
            if (!isNew){
                logicDeleted(merchantIDs);
            }

            //下发菜品类别
            searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
            searchable.addSearchParam("storeId_eq",menu.getStoreId());
            categoryList = dishesCategoryService.findWithSort(searchable);
            //规格
            specificationList = dishesSpecificationService.findWithSort(searchable);
            //做法类别
            makeCategoryList = dishesMakeCategoryService.findWithSort(searchable);
            //加料类别
            feedCategoryList = dishesFeedCategoryService.findWithSort(searchable);

            //做法
            makeList = dishesMakeService.findWithSort(searchable);
            //加料
            feedList = dishesFeedService.findWithSort(searchable);
            //品牌
            brandList = brandService.findWithSort(searchable);


            //成品原料
            List<Long> yuanliaoIds = dishes.stream().filter(x->x.getMaterialId()!=null).map(x->x.getMaterialId()).collect(Collectors.toList());
            //成品原料id 同原料一起下发
            if(CollectionUtils.isEmpty(materialIDs)){
                materialIDs = Lists.newArrayList();
            }
            List<Long> machMateialIds = null;
            if(CollectionUtils.isNotEmpty(yuanliaoIds)){
                //查询加工关系
                searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
                searchable.addSearchFilter("productId",SearchOperator.in,yuanliaoIds);
                List<MachiningRelation> machiningRelationList = machiningRelationService.findWithSort(searchable);
                machMateialIds = machiningRelationList.stream().map(x->x.getMaterialId()).collect(Collectors.toList());
            }
            log.info("yuanliaoIds >>>> : {}",yuanliaoIds);
            if(CollectionUtils.isNotEmpty(yuanliaoIds)){
                materialIDs.addAll(yuanliaoIds);
            }
            log.info("machMateialIds :::: --==== :{}",machMateialIds);
            if(CollectionUtils.isNotEmpty(machMateialIds)){
                materialIDs.addAll(machMateialIds);
            }
            log.info("materialIDs 2222  ::: {}",materialIDs);
        }
        List<Material> materialList = null;
        List<MaterialCategory> materialCategoryList = null;


        //物料类别 树形 （目前只有两级）
        materialCategoryList = materialCategoryService.getBuildTree(merchantGroupId,false);
        searchable.addSearchFilter(SearchFilterHelper.or(
                SearchFilterHelper.newCondition("storeId", SearchOperator.eq,menu.getStoreId()),
                SearchFilterHelper.newCondition("storeId",SearchOperator.isNull,null)
        ));
        //下发原料信息
        searchable = SearchUtils.newSearchableWidthMerchantGroupFilter(merchantGroupId);
        if(CollectionUtils.isNotEmpty(materialIDs)){
            materialIDs = materialIDs.stream().distinct().collect(Collectors.toList());
            //物料
            materialList = materialRepository.findAllById(materialIDs);
        }

        List<String> clearRediskey =null;
        //循环下发
        for (Long merchantID : merchantIDs) {
            clearRediskey = Lists.newArrayList();
            //现下发辅助信息 单位和原料类别
            //下发菜品库下的所有菜品单位
            if(CollectionUtils.isNotEmpty(unitList)){
                clearRediskey.add(releasedDishesUnits(merchantGroupId, unitList, merchantID));
            }

            //下发商品品牌
            if(CollectionUtils.isNotEmpty(brandList)){
                clearRediskey.add(releasedBrands(merchantGroupId,brandList,merchantID));
            }

            //下发商品扩展字段
            releasedDishesExtends(extendList, merchantID);

            //下发物料类别
            if(CollectionUtils.isNotEmpty(materialCategoryList)){
                releasedBranchMaterialCategorys(materialCategoryList,merchantID,merchantGroupId, "0/",0L);
                clearRediskey.add(RedisKeyHelper.getDishesKey("material_categorys",merchantID,merchantGroupId));
            }

            //下发原料
            //下发物料 及 物料规格
            if (CollectionUtils.isNotEmpty(materialList)){
                releasedBranchMaterials(materialList,merchantID,merchantGroupId);
                clearRediskey.add(RedisKeyHelper.getDishesKey("materials",merchantID,merchantGroupId));
                clearRediskey.add(RedisKeyHelper.getDishesKey("purchase_specs",merchantID,merchantGroupId));
            }

            //下发菜品信息
            //1.下发菜品库下的所有菜品类别
            if(CollectionUtils.isNotEmpty(categoryList)) {
                clearRediskey.add(releasedDishesCategorys(merchantGroupId, categoryList, merchantID));
            }
            //2.下发菜品库下的所有菜品规格
            if(CollectionUtils.isNotEmpty(specificationList)){
                clearRediskey.add(releasedDishSpecifications(merchantGroupId, specificationList, merchantID));
            }
            //3.下发菜品库下的所有做法类别
            if(CollectionUtils.isNotEmpty(makeCategoryList)){
                clearRediskey.add(releasedDishMakeCategorys(merchantGroupId, makeCategoryList, merchantID));
            }
            //4.下发菜品库下的所有加料类别
            if(CollectionUtils.isNotEmpty(feedCategoryList)){
                clearRediskey.add(releasedDishFeedCategorys(merchantGroupId, feedCategoryList, merchantID));
            }

            //5.做法
            if(CollectionUtils.isNotEmpty(makeList)){
                clearRediskey.add(releasedMakes(merchantGroupId, makeList, merchantID));
            }
            //6.加料
            if(CollectionUtils.isNotEmpty(feedList)){
                clearRediskey.add(releasedFeeds(merchantGroupId, feedList, merchantID));
            }
            //7.菜品
            if(CollectionUtils.isNotEmpty(dishes)){
                log.info(">>>>>>>>>>>>>>>>>::"+JSON.toJSONString(dishes));
                clearRediskey.add(releasedDishess(merchantGroupId, menu.getStoreId(), dishes, merchantID));
            }



            if (menu.getCostCard()){
                //下发成本卡
                if(CollectionUtils.isNotEmpty(materialCostList)){
                    releasedBranchMaterialCosts(materialCostList,merchantID,merchantGroupId);
                }
            }
            redisTemplate.delete(clearRediskey);
        }


    }

    /**
     * 下发商品扩展字段
     * @param
     * @param extendList
     * @param merchantID
     */
    private void releasedDishesExtends(List<DishesExtend> extendList, Long merchantID) {
//        先删除单店的字段
        String sql = "DELETE from dishes_extends where merchant_id = :merchantIDs";
        QyMap param = QyMap.map("merchantIDs",merchantID);
        branchJdbcTemplate.update(sql,param);
        //下发
        if(CollectionUtils.isNotEmpty(extendList)){
            for (DishesExtend dishesExtend : extendList) {
                param = QyMap.map("merchant_id",merchantID)
                        .setv("name",dishesExtend.getName());
                sql = "INSERT INTO dishes_extends(create_at,is_deleted,status,merchant_id,name) VALUES(now(),0,0,:merchant_id,:name)";
                branchJdbcTemplate.update(sql,param);
            }
        }

    }


    /**
     * 下发品牌信息
     * @param merchantGroupId
     * @param brandList
     * @param merchantID
     * @return
     */
    private String releasedBrands(Long merchantGroupId, List<Brand> brandList, Long merchantID) {
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        for (Brand brand : brandList) {
            sql = "SELECT * from brands where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",brand.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);
            map =  QyMap.map("merchantId",merchantID);
            map.setv("name",brand.getName());
            map.setv("uuid",brand.getUuid());
            map.setv("updateTimestamp",brand.getUpdateTimestamp());
            map.setv("deleted",brand.isDeleted());
            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT into brands (create_at,is_deleted,status,merchant_id,name,uuid,update_timestamp)\n" +
                        "VALUES(now(),:deleted,0,:merchantId,:name,:uuid,:updateTimestamp)";
                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(qyMap.getLong("update_timestamp")!=brand.getUpdateTimestamp().intValue()){
                    //修改
                    sql = "update brands set update_at=now(),is_deleted=:deleted,name=:name,update_timestamp=:updateTimestamp  " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
            saveRedis(merchantGroupId,merchantID,brand.getId(),cid,"brands");
        }
        return RedisKeyHelper.getDishesKey("brands", merchantID, merchantGroupId);
    }


    /**
     * 下发数据 菜谱 （菜品库 菜品 规格 规格关系 菜品类别 做法分类 做法）
     * @param bIDs 分店ids
     * @param dIDs 菜品ids
     * @param changeBranch 是否更改菜品库
     * @param merchantGroupId 连锁商户组id
     * @param storeId 菜品库
     */
    public void updateMenu(List<Long> bIDs,List<Long> dIDs,Map<Long,Boolean> changeBranch,Long merchantGroupId,Long storeId){
        if(CollectionUtils.isEmpty(bIDs) || CollectionUtils.isEmpty(dIDs)){
            throw new BusinessRunTimeException("数据为空",10001);
        }
        //1.将分店id 转换成merchantIds
        Set<Long> merchantIDs = changeMerchants(bIDs);
        if(CollectionUtils.isEmpty(merchantIDs)){
            throw new BusinessRunTimeException("分店商户id 为空",10001);
        }
        //判断该店面是否更改了菜品库，如果已经更改，则删除（逻辑删除）所有与菜品相关数据
        List<Long> mIds = Lists.newArrayList();
        if (MapUtils.isNotEmpty(changeBranch)){
            for (Long merchantID : merchantIDs) {
                if(changeBranch.get(merchantID)){
                    mIds.add(merchantID);
                }
            }
            //物理删除 所有与菜品相关的数据
            if(CollectionUtils.isNotEmpty(mIds)){
                deleteDishes(mIds);
            }
        }
        //用uuid和店面ID 判断数据是否在单店系统中存在（返回ID），
//        如果存在(根据更新时间戳比较是否要更新)则更新，不存在则insert(得到insert后的ID)
//        保存redis
//        表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
        //查询菜品
        List<Dishes> dishes = dishesRepository.findAllById(dIDs);
        if(CollectionUtils.isEmpty(dishes)){
            throw new BusinessRunTimeException("下发的菜品数据为空",10001);
        }

        //下发菜品库 将所有总部下发菜品信息逻辑删除
        logicDeleted(merchantIDs);

        Searchable searchable = null;
        //下发菜品类别
        searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
        searchable.addSearchParam("storeId_eq",storeId);
        List<DishesCategory> categoryList = dishesCategoryService.findWithSort(searchable);
        //规格
        List<DishesSpecification> specificationList = dishesSpecificationService.findWithSort(searchable);
        //做法类别
        List<DishesMakeCategory> makeCategoryList = dishesMakeCategoryService.findWithSort(searchable);
        //加料类别
        List<DishesFeedCategory> feedCategoryList = dishesFeedCategoryService.findWithSort(searchable);
        //单位
        List<DishesUnit> unitList = dishesUnitService.findWithSort(searchable);
        //做法
        List<DishesMake> makeList = dishesMakeService.findWithSort(searchable);
        //加料
        List<DishesFeed> feedList = dishesFeedService.findWithSort(searchable);
        List<String> clearRediskey =null;
        for (Long merchantID : merchantIDs) {
            clearRediskey = Lists.newArrayList();
            //1.下发菜品库下的所有菜品类别
            if(CollectionUtils.isNotEmpty(categoryList)) {
               clearRediskey.add(releasedDishesCategorys(merchantGroupId, categoryList, merchantID));
            }
            //2.下发菜品库下的所有菜品规格
            if(CollectionUtils.isNotEmpty(specificationList)){
               clearRediskey.add(releasedDishSpecifications(merchantGroupId, specificationList, merchantID));
            }
            //3.下发菜品库下的所有做法类别
            if(CollectionUtils.isNotEmpty(makeCategoryList)){
                clearRediskey.add(releasedDishMakeCategorys(merchantGroupId, makeCategoryList, merchantID));
            }
            //4.下发菜品库下的所有加料类别
            if(CollectionUtils.isNotEmpty(feedCategoryList)){
                clearRediskey.add(releasedDishFeedCategorys(merchantGroupId, feedCategoryList, merchantID));
            }
            //5.下发菜品库下的所有菜品单位
            if(CollectionUtils.isNotEmpty(unitList)){
                clearRediskey.add(releasedDishesUnits(merchantGroupId, unitList, merchantID));
            }
            //5.做法
            if(CollectionUtils.isNotEmpty(makeList)){
                clearRediskey.add(releasedMakes(merchantGroupId, makeList, merchantID));
            }
            //6.加料
            if(CollectionUtils.isNotEmpty(feedList)){
                clearRediskey.add(releasedFeeds(merchantGroupId, feedList, merchantID));
            }
            //7.菜品
            if(CollectionUtils.isNotEmpty(dishes)){
                clearRediskey.add(releasedDishess(merchantGroupId, storeId, dishes, merchantID));
            }
            //dishes_categorys:25:1, dishes_specifications:25:1,
            // dishes_make_categorys:25:1, dishes_feed_categorys:25:1,
            // dishes_units:25:1, dishes_practices:25:1,
            // dishes_feeds:25:1, dishess:25:1
            redisTemplate.delete(clearRediskey);
        }

    }

    /**
     * 逻辑删除分店菜品信息
     * @param mIds 下发的商户ids
     */
    private void logicDeleted(Set<Long> mIds) {
        String sql = "";
        if(CollectionUtils.isNotEmpty(mIds)){
            QyMap map = QyMap.map("merchantId",mIds);
//            sql = "update dishes_make_relations set is_deleted = 1 where uuid IS NOT NULL  and merchant_id in(:merchantId)"; //--做法关系
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_practices set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in( :merchantId)"; // 做法
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_practices set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in( :merchantId) "; //-- 做法
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_make_categorys set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in( :merchantId)"; //-- 做法类别
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_feed_relations set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in( :merchantId)"; // -- 加料关系
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_feeds set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in (:merchantId)"; //; -- 加料
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_feed_categorys set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in (:merchantId)";//;-- 加料类别
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_specification_relations set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in ( :merchantId)"; //; -- 规格关系
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_specifications set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in ( :merchantId)"; //; -- 规格
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_package_details set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in( :merchantId )"; //; -- 套餐明细
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_package_groups set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in (:merchantId) "; //; -- 套餐分组
//            branchJdbcTemplate.update(sql,map);
            sql = "update dishess set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in (:merchantId)";
            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_categorys set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in( :merchantId)";
//            branchJdbcTemplate.update(sql,map);
//            sql = "update dishes_units set is_deleted = 1 where uuid IS NOT NULL  and  merchant_id in( :merchantId)";
//            branchJdbcTemplate.update(sql,map);
        }
    }

    /**
     * 下发菜品信息 有套菜的下发套餐明细对应的菜品信息
     * @param merchantGroupId
     * @param storeId
     * @param dishes
     * @param merchantID
     * @return
     */
    private String releasedDishess(Long merchantGroupId, Long storeId, List<Dishes> dishes, Long merchantID) {
        String names;
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        String redisKey;
        BoundHashOperations<String, String, String> hashOperations;
        Searchable searchable;
        List<DishesSpecificationRelation> specificationRelationList;
        List<DishesMakeRelation> makeRelationList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        List<DishesFeedRelation> feedRelationList;
        List<DishesPackageGroup> packageGroupList;
        List<DishesPackageDetail> packageDetailList;
        List<Long> dids = Lists.newArrayList();
        //套餐明细中的菜品添加到所有要下发的菜品中
        for (Dishes dish : dishes) {
            if(dish.getType()==DishesType.PACKAGE){
                searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
                searchable.addSearchParam("packId_eq",dish.getId());
                //套餐分组
                packageGroupList = dishesPackageGroupService.findWithSort(searchable);
                if(CollectionUtils.isNotEmpty(packageGroupList)){
                    for (DishesPackageGroup group : packageGroupList) {
                        searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
                        searchable.addSearchParam("groupId_eq",group.getId());
                        packageDetailList = dishesPackageDetailService.findWithSort(searchable);
                        if(CollectionUtils.isNotEmpty(packageDetailList)) {
                            for (DishesPackageDetail detail : packageDetailList) {
                                dids.add(detail.getDishesId());
                            }
                        }
                    }
                }
            }
        }
        if(CollectionUtils.isNotEmpty(dids)){
            dishes.addAll(dishesRepository.findAllById(dids));
        }
        //先添加菜品 信息
        releasedEditDishes(merchantGroupId,storeId,dishes,merchantID);

        //添加套餐 | 规格关系 | 加料关系 | 做法关系
        for (Dishes dish : dishes) {
            //套餐
            redisKey = RedisKeyHelper.getDishesKey("dishess",merchantID,merchantGroupId);
            hashOperations= redisTemplate.boundHashOps(redisKey);
            cid = Long.valueOf(hashOperations.get(dish.getId().toString()));
            if(dish.getType()==DishesType.PACKAGE){
                releasedDishesPackages(merchantGroupId, cid, merchantID, dish);
            }

            //删除菜品相关 规格关系/做法关系/加料关系
            deletedDishesRelations(cid);

            //规格关系
            searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
            searchable.addSearchParam("storeId_eq",storeId);
            searchable.addSearchParam("dishesId_eq",dish.getId());
            specificationRelationList = dishesSpecificationRelationService.findWithSort(searchable);
            if(CollectionUtils.isNotEmpty(specificationRelationList)){
                releasedDishesSpecificationRelations(merchantGroupId, cid, specificationRelationList, merchantID);
            }
            //做法关系
            makeRelationList = dishesMakeRelationService.findWithSort(searchable);
            if(CollectionUtils.isNotEmpty(makeRelationList)){
                releasedmakeRelations(merchantGroupId, cid, makeRelationList, merchantID);
            }

            //加料关系
            feedRelationList = dishesFeedRelationService.findWithSort(searchable);
            if(CollectionUtils.isNotEmpty(feedRelationList)){
                releasedFeedRelations(merchantGroupId, cid, feedRelationList, merchantID);
            }

        }
        return RedisKeyHelper.getDishesKey("dishess",merchantID,merchantGroupId);
    }

    /**
     * 下发菜品 信息
     * @param merchantGroupId
     * @param storeId 菜品库
     * @param dishes 菜品
     * @param merchantID 商户id
     */
    void releasedEditDishes(Long merchantGroupId, Long storeId, List<Dishes> dishes, Long merchantID){
        String names;
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        String redisKey;
        BoundHashOperations<String, String, String> hashOperations;
        Searchable searchable;
        List<DishesSpecificationRelation> specificationRelationList;
        List<DishesMakeRelation> makeRelationList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        for (Dishes dish : dishes) {
            names = "";
            sql = "SELECT * from dishess where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",dish.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);

            map =  QyMap.map("merchantId",merchantID)
                    .setv("name",dish.getName())
                    .setv("spell",dish.getSpell())
                    .setv("pinyin",dish.getPinyin())
                    .setv("no",dish.getNo())
                    .setv("nameEn",dish.getNameEn());
            redisKey = RedisKeyHelper.getDishesKey("dishes_categorys",merchantID,merchantGroupId);
            hashOperations= redisTemplate.boundHashOps(redisKey);
            map.setv("categoryId",hashOperations.get(dish.getCategory().getId().toString()))
                    .setv("unit",dish.getUnit())
                    .setv("weigh",dish.getWeigh())
                    .setv("season",dish.getSeason())
                    .setv("commission",dish.getCommission())
                    .setv("commissionType",dish.getCommissionType().getKey())
                    .setv("commissionValue",dish.getCommissionValue())
                    .setv("futureCost",dish.getFutureCost())
                    .setv("price",dish.getPrice())
                    .setv("vipPrice",dish.getVipPrice())
                    .setv("hot",dish.getHot())
                    .setv("recommend",dish.getRecommend())
                    .setv("img",dish.getImg())
                    .setv("introduction",dish.getIntroduction())
                    .setv("state",dish.getState().getKey())
                    .setv("rank",dish.getRank())
                    .setv("extend",dish.getExtend());
            redisKey = RedisKeyHelper.getDishesKey("brands",merchantID,merchantGroupId);
            hashOperations= redisTemplate.boundHashOps(redisKey);
                    map.setv("brandId",dish.getBrandId()==null?null:hashOperations.get(dish.getBrandId().toString()));
            searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
            searchable.addSearchParam("dishesId_eq",dish.getId());
            searchable.addSearchParam("storeId_eq",storeId);
            specificationRelationList = dishesSpecificationRelationService.findWithSort(searchable);
            if(CollectionUtils.isNotEmpty(specificationRelationList)){
                for (DishesSpecificationRelation relation : specificationRelationList) {
                    names += relation.getSpecName()+",";
                }
            }
            if(StringUtils.isNotBlank(names)){
                names = names.substring(0,names.length()-1);
            }
            map.setv("dishesSpecificationsName",names);

            names = "";
            makeRelationList = dishesMakeRelationService.findWithSort(searchable);
            if(CollectionUtils.isNotEmpty(makeRelationList)){
                for (DishesMakeRelation relation : makeRelationList) {
                    names += relation.getName()+",";
                }
            }
            if(StringUtils.isNotBlank(names)){
                names = names.substring(0,names.length()-1);
            }
            map.setv("dishesMakeRelationsName",names);

            map.setv("type",dish.getType().getKey())
                    .setv("priceMode",dish.getPriceMode().getKey())
                    .setv("packType",dish.getPackType().getKey())
                    .setv("remark",dish.getRemark())
                    .setv("uuid",dish.getUuid())
                    .setv("updateTimestamp",dish.getUpdateTimestamp())
            .setv("deleted",dish.isDeleted())
                    .setv("code",dish.getCode());
            if(dish.getMaterialId()!=null){
                redisKey = RedisKeyHelper.getDishesKey("materials",merchantID,merchantGroupId);
                hashOperations= redisTemplate.boundHashOps(redisKey);
                log.info("-----------------fff: {}",dish.getMaterialId().toString());
                log.info("-----------------vvv: {}",hashOperations.get(dish.getMaterialId().toString()));
                map.setv("material_id",hashOperations.get(dish.getMaterialId().toString()));
            }else {
                map.setv("material_id",dish.getMaterialId());
            }

            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT into dishess (create_at,is_deleted,status,merchant_id,name,spell,pinyin,no,name_en,category_id,unit," +
                        "weigh,season,commission,commission_type,commission_value,future_cost,price,vip_price,hot," +
                        "recommend,img,introduction,state,rank,dishes_specifications_name,dishes_make_relations_name," +
                        "type,price_mode,pack_type,remark,uuid,update_timestamp,material_id,code,brand_id,extend)\n" +
                        "VALUES(now(),:deleted,0,:merchantId,:name,:spell,:pinyin,:no,:nameEn,:categoryId,:unit," +
                        ":weigh,:season,:commission,:commissionType,:commissionValue,:futureCost,:price,:vipPrice,:hot," +
                        ":recommend,:img,:introduction,:state,:rank,:dishesSpecificationsName,:dishesMakeRelationsName," +
                        ":type,:priceMode,:packType,:remark,:uuid,:updateTimestamp,:material_id,:code,:brandId,:extend)\n";

                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
//                if(qyMap.getLong("update_timestamp")!=dish.getUpdateTimestamp().intValue()){
                    //修改
                    sql = "update dishess set update_at=now(),is_deleted=:deleted,name=:name,spell=:spell,pinyin=:pinyin,no=:no,name_en=:nameEn,category_id=:categoryId,unit=:unit," +
                            " weigh=:weigh,season=:season,commission=:commission,commission_type=:commissionType,commission_value=:commissionValue,future_cost=:futureCost,price=:price,vip_price=:vipPrice,hot=:hot,"+
                            " recommend=:recommend,img=:img,introduction=:introduction,state=:state,rank=:rank,dishes_specifications_name=:dishesSpecificationsName,dishes_make_relations_name=:dishesMakeRelationsName,"+
                            " type=:type,price_mode=:priceMode,pack_type=:packType,remark=:remark,update_timestamp=:updateTimestamp,material_id=:material_id,code=:code,brand_id=:brandId,extend=:extend " +
                            "where merchant_id= :merchantId and uuid = :uuid";
                    branchJdbcTemplate.update(sql,map);
//                }
                cid = qyMap.getLong("id");

            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
            saveRedis(merchantGroupId,merchantID,dish.getId(),cid,"dishess");
        }

    }

    /**
     * 下发套餐分组 和 套餐明细
     * @param merchantGroupId
     * @param cid 单店对应菜品id
     * @param merchantID
     * @param dish 连锁菜品信息
     */
    private void releasedDishesPackages(Long merchantGroupId, Long cid, Long merchantID, Dishes dish) {
        String sql;
        QyMap map;
        Searchable searchable;
        List<DishesPackageGroup> packageGroupList;
        List<DishesPackageDetail> packageDetailList;
        String redisKey;
        BoundHashOperations<String, String, String> hashOperations;
        if(dish.getType()== DishesType.PACKAGE){
            //删除套餐分组 和 套餐明细
            sql = "DELETE from dishes_package_details where group_id in(SELECT id from dishes_package_groups where pack_id = :dishesId)";
            map = QyMap.map("dishesId",cid);
            branchJdbcTemplate.update(sql,map);
            sql = "DELETE from dishes_package_groups where pack_id = :dishesId";
            branchJdbcTemplate.update(sql,map);

            searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
            searchable.addSearchParam("packId_eq",dish.getId());
            //套餐分组
            packageGroupList = dishesPackageGroupService.findWithSort(searchable);



            if(CollectionUtils.isNotEmpty(packageGroupList)){
                for (DishesPackageGroup group : packageGroupList) {
                    sql = "INSERT into dishes_package_groups(create_at,is_deleted,status,merchant_id,count,has_repeat,name,total,pack_id)\n" +
                            "VALUES(now(),:deleted,0,:merchantId,:count,:hasRepeat,:name,:total,:packId)";
                    map = QyMap.map("merchantId",merchantID)
                            .setv("count",group.getCount())
                            .setv("hasRepeat",group.getHasRepeat())
                            .setv("name",group.getName())
                            .setv("total",group.getTotal())
                            .setv("packId",cid)
                    .setv("deleted",group.isDeleted());
                    Long gid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
                    packageDetailList = null;
                    //添加明细
                    searchable = SearchUtils.newSearchableWithMerchantFilter(merchantGroupId);
                    searchable.addSearchParam("groupId_eq",group.getId());
                    packageDetailList = dishesPackageDetailService.findWithSort(searchable);
                    if(CollectionUtils.isNotEmpty(packageDetailList)){
                        for (DishesPackageDetail detail : packageDetailList) {
                            sql = "INSERT into dishes_package_details(create_at,is_deleted,status,merchant_id,alternative,count,def,diff,spec_id,weight,dishes_id,group_id,price,spec_name)\n" +
                                    "VALUES(now(),:deleted,0,:merchantId,:alternative,:count,:def,:diff,:specId,:weight,:dishesId,:groupId,:price,:specName)";
                            map = QyMap.map("merchantId",merchantID)
                                    .setv("alternative",detail.getAlternative())
                                    .setv("count",detail.getCount())
                                    .setv("def",detail.getDef())
                                    .setv("deleted",detail.isDeleted())
                                    .setv("diff",detail.getDiff());
                            if(detail.getSpecId()!=null){
                                redisKey = RedisKeyHelper.getDishesKey("dishes_specifications",merchantID,merchantGroupId);
                                hashOperations= redisTemplate.boundHashOps(redisKey);
                                map.setv("specId",hashOperations.get(detail.getSpecId().toString()));
                            }else {
                                map.setv("specId",null);
                            }
                            map.setv("weight",0);
                            redisKey = RedisKeyHelper.getDishesKey("dishess",merchantID,merchantGroupId);
                            hashOperations= redisTemplate.boundHashOps(redisKey);
                            map.setv("dishesId",hashOperations.get(detail.getDishesId().toString()))
                                    .setv("groupId",gid)
                                    .setv("price",detail.getPrice())
                                    .setv("specName",detail.getSpecName());
                            branchJdbcTemplate.update(sql,map);
                        }
                    }

                }
            }
        }
    }

    /**
     * 删除菜品相关 规格关系/做法关系/加料关系
     * @param cid 单店系统中菜品id
     */
    private void deletedDishesRelations(Long cid) {
        String sql;
        QyMap map;//删除关系
        sql = "DELETE from dishes_specification_relations where dishes_id = :dishesId";
        map = QyMap.map("dishesId",cid);
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_feed_relations where dishes_id = :dishesId";
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_make_relations where dishes_id = :dishesId";
        branchJdbcTemplate.update(sql,map);
    }

    /**
     * 下发规格关系
     * @param merchantGroupId
     * @param cid 单店系统中菜品id
     * @param specificationRelationList
     * @param merchantID
     */
    private void releasedDishesSpecificationRelations(Long merchantGroupId, Long cid, List<DishesSpecificationRelation> specificationRelationList, Long merchantID) {
        String sql;
        QyMap map;
        String redisKey;
        BoundHashOperations<String, String, String> hashOperations;
        for (DishesSpecificationRelation relation : specificationRelationList) {
            sql = "INSERT into dishes_specification_relations(create_at,is_deleted,status,merchant_id,def,price,vip_price,dishes_id,spec_id)\n" +
                    "VALUES(now(),:deleted,0,:merchantId,:def,:price,:vipPrice,:dishesId,:specId)";
            map = QyMap.map("merchantId",merchantID)
                    .setv("def",relation.getDef())
                    .setv("price",relation.getPrice())
                    .setv("vipPrice",relation.getVipPrice())
                    .setv("dishesId",cid)
                    .setv("deleted",relation.isDeleted());
            if(relation.getSpecId()!=null){
                redisKey = RedisKeyHelper.getDishesKey("dishes_specifications",merchantID,merchantGroupId);
                hashOperations= redisTemplate.boundHashOps(redisKey);
                map.setv("specId",hashOperations.get(relation.getSpecId().toString()));
            }else {
                map.setv("specId",null);
            }

            branchJdbcTemplate.update(sql,map);
        }
    }

    /**
     * 下发做法关系
     * @param merchantGroupId
     * @param cid 单店系统中菜品id
     * @param makeRelationList
     * @param merchantID
     */
    private void releasedmakeRelations(Long merchantGroupId, Long cid, List<DishesMakeRelation> makeRelationList, Long merchantID) {
        String sql;
        QyMap map;
        String redisKey;
        BoundHashOperations<String, String, String> hashOperations;
        for (DishesMakeRelation relation : makeRelationList) {
            sql = "INSERT into dishes_make_relations(create_at,is_deleted,status,merchant_id,name,type,val,dishes_id,make_id,def,make_category_id,make_category_name)\n" +
                    " VALUES(now(),:deleted,0,:merchantId,:name,:type,:val,:disheId,:makeId,:def,:makeCategoryId,:makeCategoryName);";
            map = QyMap.map("merchantId",merchantID)
                    .setv("name",relation.getName())
                    .setv("type",relation.getPriceupType().getKey())
                    .setv("val",relation.getVal())
                    .setv("disheId",cid)
                    .setv("deleted",relation.isDeleted());

            redisKey = RedisKeyHelper.getDishesKey("dishes_practices",merchantID,merchantGroupId);
            hashOperations= redisTemplate.boundHashOps(redisKey);
            map.setv("makeId",hashOperations.get(relation.getMakeId().toString()))
                    .setv("def",relation.getDef());
            redisKey = RedisKeyHelper.getDishesKey("dishes_make_categorys",merchantID,merchantGroupId);
            hashOperations= redisTemplate.boundHashOps(redisKey);
            map.setv("makeCategoryId",hashOperations.get(relation.getMakeCategoryId().toString()))
                    .setv("makeCategoryName",relation.getMakeCategoryName());
            branchJdbcTemplate.update(sql,map);
        }
    }

    /**
     * 下发加料关系
     * @param merchantGroupId
     * @param cid 单店系统中菜品id
     * @param feedRelationList 关系集合
     * @param merchantID
     */
    private void releasedFeedRelations(Long merchantGroupId, Long cid, List<DishesFeedRelation> feedRelationList, Long merchantID) {
        String sql;
        QyMap map;
        String redisKey;
        BoundHashOperations<String, String, String> hashOperations;
        for (DishesFeedRelation relation : feedRelationList) {
            sql = "INSERT into dishes_feed_relations(create_at,is_deleted,status,merchant_id,category_id,category_name,dishes_id,feed_id,name,price)\n" +
                    " VALUES(now(),:deleted,0,:merchantId,:categoryId,:categoryName,:dishesId,:feedId,:name,:price);";
            map = QyMap.map("merchantId",merchantID);
            redisKey = RedisKeyHelper.getDishesKey("dishes_feed_categorys",merchantID,merchantGroupId);
            hashOperations= redisTemplate.boundHashOps(redisKey);
            map.setv("categoryId",hashOperations.get(relation.getCategoryId().toString()))
                    .setv("categoryName",relation.getCategoryName())
                    .setv("dishesId",cid);
            redisKey = RedisKeyHelper.getDishesKey("dishes_feeds",merchantID,merchantGroupId);
            hashOperations= redisTemplate.boundHashOps(redisKey);
            map.setv("feedId",hashOperations.get(relation.getFeedId().toString()))
                    .setv("name",relation.getName())
                    .setv("price",relation.getPrice())
                    .setv("deleted",relation.isDeleted());
            branchJdbcTemplate.update(sql,map);
        }
    }

    /**
     * 下发菜品加料
     * @param merchantGroupId
     * @param feedList 加料集合
     * @param merchantID
     * @return
     */
    private String releasedFeeds(Long merchantGroupId, List<DishesFeed> feedList, Long merchantID) {
        String redisKey;
        BoundHashOperations<String, String, String> hashOperations;
        Long cid;
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Map<String, Object> maps;
        QyMap qyMap;
        for (DishesFeed feed: feedList) {
            redisKey = RedisKeyHelper.getDishesKey("dishes_feed_categorys",merchantID,merchantGroupId);
            hashOperations= redisTemplate.boundHashOps(redisKey);
            //得到单店系统中 加料类别id
            cid = Long.valueOf(hashOperations.get(feed.getType().getId().toString()));
            //查询
            sql = "SELECT * from dishes_feeds where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",feed.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);

            map =  QyMap.map("merchantId",merchantID);
            map.setv("name",feed.getName());
            map.setv("state",feed.getState().getKey());
            map.setv("uuid",feed.getUuid());
            map.setv("updateTimestamp",feed.getUpdateTimestamp());
            map.setv("price",feed.getPrice());
            map.setv("typeId",cid);
            map.setv("deleted",feed.isDeleted());

            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT into dishes_feeds (create_at,is_deleted,status,merchant_id,name,price,state,type_id,uuid,update_timestamp)\n" +
                        "VALUES(now(),:deleted,0,:merchantId,:name,:price,:state,:typeId,:uuid,:updateTimestamp)";
                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(qyMap.getLong("update_timestamp")!=feed.getUpdateTimestamp().intValue()){
                    //修改
                    sql = "update dishes_feeds set update_at=now(),is_deleted=:deleted,name=:name,state = :state,price=:price,type_id=:typeId,update_timestamp=:updateTimestamp  " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
            saveRedis(merchantGroupId,merchantID,feed.getId(),cid,"dishes_feeds");
        }
        return RedisKeyHelper.getDishesKey("dishes_feeds", merchantID, merchantGroupId);
    }

    /**
     * 下发菜品做法
     * @param merchantGroupId
     * @param makeList 做法集合
     * @param merchantID
     * @return
     */
    private String releasedMakes(Long merchantGroupId, List<DishesMake> makeList, Long merchantID) {
        String redisKey;
        BoundHashOperations<String, String, String> hashOperations;
        Long cid;
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Map<String, Object> maps;
        QyMap qyMap;
        List<String> clearRediskey = null;
        for (DishesMake make : makeList) {
            redisKey = RedisKeyHelper.getDishesKey("dishes_make_categorys",merchantID,merchantGroupId);
            hashOperations= redisTemplate.boundHashOps(redisKey);
            //得到单店系统中 做法类别id
            cid =  Long.valueOf(hashOperations.get(make.getType().getId().toString()));
            //查询
            sql = "SELECT * from dishes_practices where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",make.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);

            map =  QyMap.map("merchantId",merchantID);
            map.setv("name",make.getName());
            map.setv("state",make.getState().getKey());
            map.setv("uuid",make.getUuid());
            map.setv("updateTimestamp",make.getUpdateTimestamp());
            map.setv("priceupType",make.getPriceupType().getKey());
            map.setv("priceupValue",make.getPriceupValue());
            map.setv("typeId",cid);
            map.setv("deleted",make.isDeleted());

            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT into dishes_practices (create_at,is_deleted,status,merchant_id,name,priceup_type,priceup_value,state,type_id,uuid,update_timestamp)\n" +
                        "VALUES(now(),:deleted,0,:merchantId,:name,:priceupType,:priceupValue,:state,:typeId,:uuid,:updateTimestamp)";
                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(qyMap.getLong("update_timestamp")!=make.getUpdateTimestamp().intValue()){
                    //修改
                    sql = "update dishes_practices set update_at=now(),is_deleted=:deleted,name=:name,state = :state,priceup_type=:priceupType,priceup_value=:priceupValue,type_id=:typeId,update_timestamp=:updateTimestamp " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
            saveRedis(merchantGroupId,merchantID,make.getId(),cid,"dishes_practices");
        }
        return RedisKeyHelper.getDishesKey("dishes_practices", merchantID, merchantGroupId);
    }

    /**
     * 下发菜品单位
     * @param merchantGroupId
     * @param unitList 菜品单位集合
     * @param merchantID
     * @return
     */
    private String releasedDishesUnits(Long merchantGroupId, List<DishesUnit> unitList,  Long merchantID) {
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        List<String> clearRediskey = null;
        for (DishesUnit unit : unitList) {
            sql = "SELECT * from dishes_units where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",unit.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);

            map =  QyMap.map("merchantId",merchantID);
            map.setv("name",unit.getName());
            map.setv("state",unit.getState().getKey());
            map.setv("uuid",unit.getUuid());
            map.setv("updateTimestamp",unit.getUpdateTimestamp());
            map.setv("remark",unit.getRemark());
            map.setv("deleted",unit.isDeleted());

            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT into dishes_units (create_at,is_deleted,status,merchant_id,name,remark,state,uuid,update_timestamp)\n" +
                        "VALUES(now(),:deleted,0,:merchantId,:name,:remark,:state,:uuid,:updateTimestamp)";
                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(qyMap.getLong("update_timestamp")!=unit.getUpdateTimestamp().intValue()){
                    //修改
                    sql = "update dishes_units set update_at=now(),is_deleted=:deleted,name=:name,remark=:remark,state = :state,update_timestamp=:updateTimestamp  " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
            saveRedis(merchantGroupId,merchantID,unit.getId(),cid,"dishes_units");
        }
        return RedisKeyHelper.getDishesKey("dishes_units", merchantID, merchantGroupId);
    }

    /**
     * 下发菜品加料类别
     * @param merchantGroupId
     * @param feedCategoryList 加料类别集合
     * @param merchantID
     * @return
     */
    private String releasedDishFeedCategorys(Long merchantGroupId, List<DishesFeedCategory> feedCategoryList,  Long merchantID) {
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        List<String> clearRediskey= null;
        for (DishesFeedCategory feedCategory : feedCategoryList) {
            sql = "SELECT * from dishes_feed_categorys where merchant_id = :merchantId and uuid = :uuid ";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",feedCategory.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);

            map =  QyMap.map("merchantId",merchantID);
            map.setv("name",feedCategory.getName());
            map.setv("state",feedCategory.getState().getKey());
            map.setv("uuid",feedCategory.getUuid());
            map.setv("updateTimestamp",feedCategory.getUpdateTimestamp());
            map.setv("deleted",feedCategory.isDeleted());

            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT into dishes_feed_categorys (create_at,is_deleted,status,merchant_id,name,state,uuid,update_timestamp)\n" +
                        "VALUES(now(),:deleted,0,:merchantId,:name,:state,:uuid,:updateTimestamp)";
                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(qyMap.getLong("update_timestamp")!=feedCategory.getUpdateTimestamp().intValue()){
                    //修改
                    sql = "update dishes_feed_categorys set update_at=now(),is_deleted=:deleted,name=:name,state = :state,update_timestamp=:updateTimestamp " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
            saveRedis(merchantGroupId,merchantID,feedCategory.getId(),cid,"dishes_feed_categorys");
        }
        return RedisKeyHelper.getDishesKey("dishes_feed_categorys", merchantID, merchantGroupId);
    }

    /**
     * 下发 菜品做法类型
     * @param merchantGroupId
     * @param makeCategoryList 菜品做法
     * @param merchantID
     * @return
     */
    private String releasedDishMakeCategorys(Long merchantGroupId, List<DishesMakeCategory> makeCategoryList,  Long merchantID) {
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        for (DishesMakeCategory makeCategory : makeCategoryList) {
            sql = "SELECT * from dishes_make_categorys where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",makeCategory.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);

            map =  QyMap.map("merchantId",merchantID);
            map.setv("chooseType",makeCategory.getChooseType().getKey());
            map.setv("name",makeCategory.getName());
            map.setv("state",makeCategory.getState().getKey());
            map.setv("uuid",makeCategory.getUuid());
            map.setv("updateTimestamp",makeCategory.getUpdateTimestamp());
            map.setv("deleted",makeCategory.isDeleted());

            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT into dishes_make_categorys (create_at,is_deleted,status,merchant_id,choose_type,name,state,uuid,update_timestamp)\n" +
                        "VALUES(now(),:deleted,0,:merchantId,:chooseType,:name,:state,:uuid,:updateTimestamp)";
                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(qyMap.getLong("update_timestamp")!=makeCategory.getUpdateTimestamp().intValue()){
                    //修改
                    sql = "update dishes_make_categorys set update_at=now(),is_deleted=:deleted,choose_type=:chooseType,name=:name,state = :state,update_timestamp=:updateTimestamp " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
            saveRedis(merchantGroupId,merchantID,makeCategory.getId(),cid,"dishes_make_categorys");
        }
        return RedisKeyHelper.getDishesKey("dishes_make_categorys", merchantID, merchantGroupId);
    }

    /**
     * 下发菜品规格
     * @param merchantGroupId
     * @param specificationList 规格list
     * @param merchantID
     * @return
     */
    private String releasedDishSpecifications(Long merchantGroupId, List<DishesSpecification> specificationList, Long merchantID) {
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        for (DishesSpecification specification : specificationList) {
            sql = "SELECT * from dishes_specifications where merchant_id = :merchantId and uuid = :uuid";
            map =  QyMap.map("merchantId",merchantID).setv("uuid",specification.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql,map);

            map =  QyMap.map("merchantId",merchantID);
            map.setv("name",specification.getName());
            map.setv("state",specification.getState().getKey());
            map.setv("uuid",specification.getUuid());
            map.setv("updateTimestamp",specification.getUpdateTimestamp());
            map.setv("deleted", specification.isDeleted());

            if(CollectionUtils.isEmpty(mapList)){
                //添加
                sql = "INSERT into dishes_specifications (create_at,is_deleted,status,merchant_id,name,state,uuid,update_timestamp)\n" +
                        "VALUES(now(),:deleted,0,:merchantId,:name,:state,:uuid,:updateTimestamp)";
                cid = branchJdbcTemplate.insertForAutoIncrement(sql,map);
            }else{
                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if(qyMap.getLong("update_timestamp")!=specification.getUpdateTimestamp().intValue()){
                    //修改
                    sql = "update dishes_specifications set update_at=now(),is_deleted=:deleted,name=:name,state = :state,update_timestamp=:updateTimestamp " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql,map);
                }
                cid = qyMap.getLong("id");
            }
            //表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }
           saveRedis(merchantGroupId,merchantID,specification.getId(),cid,"dishes_specifications");

        }

        return RedisKeyHelper.getDishesKey("dishes_specifications", merchantID, merchantGroupId);
    }

    /**
     * 下发菜品类别相关信息
     * @param merchantGroupId 商户组
     * @param categoryList 菜品类别
     * @param merchantID 商户id
     */
    private String releasedDishesCategorys(Long merchantGroupId, List<DishesCategory> categoryList, Long merchantID) {
        String sql;
        QyMap map;
        List<Map<String, Object>> mapList;
        Long cid;
        Map<String, Object> maps;
        QyMap qyMap;
        for (DishesCategory category : categoryList) {
            sql = "SELECT * from dishes_categorys where merchant_id = :merchantId and uuid = :uuid";
            map = QyMap.map("merchantId", merchantID).setv("uuid", category.getUuid());
            mapList = branchJdbcTemplate.queryForList(sql, map);
            map = QyMap.map("merchantId", merchantID);
            map.setv("name", category.getName());
            map.setv("no", category.getNo());
            map.setv("remark", category.getRemark());
            map.setv("state", category.getState().getKey());
            map.setv("uuid", category.getUuid());
            map.setv("updateTimestamp", category.getUpdateTimestamp());
            map.setv("deleted", category.isDeleted());

            if (CollectionUtils.isEmpty(mapList)) {

                //添加
                sql = "INSERT into dishes_categorys (create_at,is_deleted,status,merchant_id,is_package,name,no,remark,state,uuid,update_timestamp)\n" +
                        "VALUES(now(),:deleted,0,:merchantId,:isPackage,:name,:no,:remark,:state,:uuid,:updateTimestamp)";
                if (category.getNo().equals("00000")) {
                    map.setv("isPackage", true);
                } else {
                    map.setv("isPackage", false);
                }
                cid = branchJdbcTemplate.insertForAutoIncrement(sql, map);

            } else {

                maps = mapList.get(0);
                qyMap = QyMap.WRAP(maps);
                if (qyMap.getLong("update_timestamp") != category.getUpdateTimestamp().intValue()) {
                    //修改
                    sql = "update dishes_categorys set update_at=now(),is_deleted=:deleted,name=:name,no = :no,remark=:remark,state = :state,update_timestamp=:updateTimestamp " +
                            "where merchant_id= :merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
                    branchJdbcTemplate.update(sql, map);
                }
                cid = qyMap.getLong("id");
            }

//                表名+“:”+单店ID+“:”+连锁店ID  =  { 连锁版数据ID: 分店版数据ID }

            //将数据存储到redis
            saveRedis(merchantGroupId, merchantID, category.getId(),cid,"dishes_categorys");
        }

        String redisKey = RedisKeyHelper.getDishesKey("dishes_categorys", merchantID, merchantGroupId);
        return redisKey;

    }

    /**
     * redis 存储数据
     * @param merchantGroupId 商户组id
     * @param merchantID 商户id
     * @param gid 连锁数据id
     * @param cid 分店数据id
     * @param tableName 表名
     * @return
     */
    private void saveRedis(Long merchantGroupId, Long merchantID, Long gid,Long cid ,String tableName) {
        String redisKey = "";
        BoundHashOperations<String, String, String> hashOperations;
        Map<String, String> redisIdMap; //redisIdMap 存储 { 连锁版数据ID: 分店版数据ID }
        redisKey = RedisKeyHelper.getDishesKey(tableName, merchantID, merchantGroupId);
        hashOperations = redisTemplate.boundHashOps(redisKey);
        redisIdMap = Maps.newHashMap();
        redisIdMap.put(gid.toString(),cid.toString());
        hashOperations.putAll(redisIdMap);
    }


    /**
     * 物理删除菜品相关数据
     * @param mIds 商户ids
     */
    private void deleteDishes(List<Long> mIds) {
        String sql;QyMap map = QyMap.map("merchantId",mIds);
        sql = "DELETE from dishes_make_relations where merchant_id in(:merchantId)"; //--做法关系
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_practices where merchant_id in( :merchantId)"; // 做法
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_practices where merchant_id in( :merchantId) "; //-- 做法
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_make_categorys where merchant_id in( :merchantId)"; //-- 做法类别
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_feed_relations where merchant_id in( :merchantId)"; // -- 加料关系
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_feeds where merchant_id in (:merchantId)"; //; -- 加料
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_feed_categorys where merchant_id in (:merchantId)";//;-- 加料类别
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_specification_relations where merchant_id in ( :merchantId)"; //; -- 规格关系
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_specifications where merchant_id in ( :merchantId)"; //; -- 规格
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_package_details where merchant_id in( :merchantId )"; //; -- 套餐明细
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_package_groups where merchant_id in (:merchantId) "; //; -- 套餐分组
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_activity_details where merchant_id in( :merchantId)";
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from material_cost_details where merchant_id in( :merchantId)";
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from material_costs where merchant_id in( :merchantId)";
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from discount_details where merchant_id in( :merchantId)";
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishess where merchant_id in (:merchantId)";
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_categorys where merchant_id in( :merchantId)";
        log.info("dggggggggggggggg删除类别");
        branchJdbcTemplate.update(sql,map);
        sql = "DELETE from dishes_units where merchant_id in( :merchantId)";
        branchJdbcTemplate.update(sql,map);


         /*if(CollectionUtils.isNotEmpty(mIds)){
            QyMap map = QyMap.map("merchantId",mIds);
            sql = "update dishes_make_relations set is_deleted = 1 where merchant_id in(:merchantId)"; //--做法关系
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_practices set is_deleted = 1 where merchant_id in( :merchantId)"; // 做法
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_practices set is_deleted = 1 where merchant_id in( :merchantId) "; //-- 做法
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_make_categorys set is_deleted = 1 where merchant_id in( :merchantId)"; //-- 做法类别
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_feed_relations set is_deleted = 1 where merchant_id in( :merchantId)"; // -- 加料关系
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_feeds set is_deleted = 1 where merchant_id in (:merchantId)"; //; -- 加料
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_feed_categorys set is_deleted = 1 where merchant_id in (:merchantId)";//;-- 加料类别
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_specification_relations set is_deleted = 1 where merchant_id in ( :merchantId)"; //; -- 规格关系
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_specifications set is_deleted = 1 where merchant_id in ( :merchantId)"; //; -- 规格
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_package_details set is_deleted = 1 where merchant_id in( :merchantId )"; //; -- 套餐明细
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_package_groups set is_deleted = 1 where merchant_id in (:merchantId) "; //; -- 套餐分组
            branchJdbcTemplate.update(sql,map);
            sql = "update dishess set is_deleted = 1 where merchant_id in (:merchantId)";
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_categorys set is_deleted = 1 where merchant_id in( :merchantId)";
            branchJdbcTemplate.update(sql,map);
            sql = "update dishes_units set is_deleted = 1 where merchant_id in( :merchantId)";
            branchJdbcTemplate.update(sql,map);
        }*/
    }


    /**
     * 数据下发 积分规则
     * @param bIDs
     * @param dataList
     */
    public void updateIntegeralRule(List<Long> bIDs,List<IntegralRule> dataList){
        if(CollectionUtils.isEmpty(bIDs) || CollectionUtils.isEmpty(dataList)){
            throw new BusinessRunTimeException("数据为空",10001);
        }

        //1.将分店id 转换成merchantIds
        Set<Long> merchantIDs = changeMerchants(bIDs);
        if(CollectionUtils.isEmpty(merchantIDs)){
            throw new BusinessRunTimeException("分店商户id 为空",10001);
        }
        String sql = "";

        //判断单店的积分方案 是否有时间重叠 重叠将单店的积分方案禁用
        for (Long merchantID : merchantIDs) {
            for (IntegralRule rule : dataList) {

            }
        }



        //2.根据merchantid 查询单店系统中对应表的uuid和merchantID字段, 将获取到的数据转换为Map<Long, Set<String>> 格式 merchant -> Set<UUID>
        sql = "select merchant_id,uuid from charges where is_deleted=0 and merchant_id in (:merchantIds) ";
        QyMap map = QyMap.map("merchantIds",merchantIDs);
        List<Map<String,Object>> mapList = branchJdbcTemplate.queryForList(sql,map);
        //根据merchantId分组
        Map<Long, Set<String>> branchDataMap = mapList.stream()
                .map(QyMap::new)
                .filter(x->x.get("uuid")!=null)
                .collect(Collectors.groupingBy(x->x.getLong("merchant_id"), Collectors.mapping(x->x.getString("uuid"), Collectors.toSet())));
        //6.将转换后的merchantId SET集合遍历，
        // 遍历连锁店数据，
        // 依次判断数据元素uuid是否在对应单店系统的UUID的集合中存在，
        // 如果存在则update ... where merchant_id=? and update_timestamp<>? and uuid=?.  update_timestamp 取要下发数据的update_timestamp 值。
        // 否则插入数据
        Set<String> stringSet = null;
        List<QyMap> paramListUpdate = Lists.newArrayList();
        List<QyMap> paramListInsert = Lists.newArrayList();
        QyMap param = null;
        for (Long merchantID : merchantIDs) {
            stringSet = branchDataMap.get(merchantID);
            for (IntegralRule rule : dataList) {
                param = QyMap.NEW();
                param.setv("merchantId",merchantID);
                param.setv("updateTimestamp",rule.getUpdateTimestamp());
                param.setv("uuid",rule.getUuid());
                param.setv("name",rule.getName());
                param.setv("endTime",rule.getEndTime());
                param.setv("integral",rule.getIntegral());
                param.setv("price",rule.getAmount());
                param.setv("startTime",rule.getStartTime());
                param.setv("state",rule.getState().getKey());
                param.setv("immediately_exchange",rule.getImmediatelyExchange());

                if(CollectionUtils.isNotEmpty(stringSet) && stringSet.contains(rule.getUuid())){
                    //update
                    paramListUpdate.add(param);
                }else {
                    //insert
                    paramListInsert.add(param);
                }
            }
        }

        //批量执行sql
        if(CollectionUtils.isNotEmpty(paramListUpdate)){
            Map<String,?>[] params=new Map[paramListUpdate.size()];
            for (int i = 0; i < paramListUpdate.size(); i++) {
                params[i] = paramListUpdate.get(i);
            }
            sql = "UPDATE integral_exchanges set end_time=:endTime,integral=:integral,name=:name,price=:price,start_time=:startTime,state=:state,update_timestamp=:updateTimestamp,immediately_exchange=:immediately_exchange " +
                    " where merchant_id=:merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
            branchJdbcTemplate.batchUpdate(sql,params);
        }

        if(CollectionUtils.isNotEmpty(paramListInsert)){
            Map<String,?>[] params=new Map[paramListInsert.size()];
            for (int i = 0; i < paramListInsert.size(); i++) {
                params[i] = paramListInsert.get(i);
            }
            sql = "INSERT INTO integral_exchanges(create_at,is_deleted,status,merchant_id,end_time,immediately_exchange,integral,max_count,name,price,start_time,state,total,type,use_count,uuid,update_timestamp,immediately_exchange)\n" +
                    "VALUES(now(),0,0,:merchantId,:endTime,0,:integral,1,:name,:price,:startTime,:state,0,'CASH',0,:uuid,:updateTimestamp,:immediately_exchange)";
            branchJdbcTemplate.batchUpdate(sql,params);
        }
    }

    /**
     * 数据下发 服务费
     * @param bIDs 分店id
     * @param dataList 下发数据
     */
    public void updateCharge(List<Long> bIDs,List<Charge> dataList){
        if(CollectionUtils.isEmpty(bIDs) || CollectionUtils.isEmpty(dataList)){
            throw new BusinessRunTimeException("数据为空",10001);
        }

        //1.将分店id 转换成merchantIds
        Set<Long> merchantIDs = changeMerchants(bIDs);
        if(CollectionUtils.isEmpty(merchantIDs)){
            throw new BusinessRunTimeException("分店商户id 为空",10001);
        }
        //2.根据merchantid 查询单店系统中对应表的uuid和merchantID字段, 将获取到的数据转换为Map<Long, Set<String>> 格式 merchant -> Set<UUID>
        String sql = "select merchant_id,uuid from charges where merchant_id in (:merchantIds) ";
        QyMap map = QyMap.map("merchantIds",merchantIDs);
        List<Map<String,Object>> mapList = branchJdbcTemplate.queryForList(sql,map);
        //根据merchantId分组
        Map<Long, Set<String>> branchDataMap = mapList.stream()
                .map(QyMap::new)
                .filter(x->x.get("uuid")!=null)
                .collect(Collectors.groupingBy(x->x.getLong("merchant_id"), Collectors.mapping(x->x.getString("uuid"), Collectors.toSet())));
        //6.将转换后的merchantId SET集合遍历，
        // 遍历连锁店数据，
        // 依次判断数据元素uuid是否在对应单店系统的UUID的集合中存在，
        // 如果存在则update ... where merchant_id=? and update_timestamp<>? and uuid=?.  update_timestamp 取要下发数据的update_timestamp 值。
        // 否则插入数据
        Set<String> stringSet = null;
        List<QyMap> paramListUpdate = Lists.newArrayList();
        List<QyMap> paramListInsert = Lists.newArrayList();
        QyMap param = null;
        for (Long merchantID : merchantIDs) {
            stringSet = branchDataMap.get(merchantID);
            for (Charge charge : dataList) {
                param = QyMap.NEW();
                param.setv("merchantId",merchantID);
                param.setv("updateTimestamp",charge.getUpdateTimestamp());
                param.setv("uuid",charge.getUuid());
                param.setv("name",charge.getName());
                param.setv("no",charge.getNo());
                param.setv("state",charge.getState().getKey());
                param.setv("time",charge.getTime());
                param.setv("type",charge.getType().getKey());
                param.setv("value",charge.getValue());
                param.setv("deleted",charge.isDeleted());
                if(CollectionUtils.isNotEmpty(stringSet) && stringSet.contains(charge.getUuid())){
                    //update
                    paramListUpdate.add(param);
                }else {
                    //insert
                    paramListInsert.add(param);
                }
            }
        }

        //批量执行sql
        if(CollectionUtils.isNotEmpty(paramListUpdate)){
            Map<String,?>[] params=new Map[paramListUpdate.size()];
            for (int i = 0; i < paramListUpdate.size(); i++) {
                params[i] = paramListUpdate.get(i);
            }
            sql = "update charges set update_at = now(),is_deleted=:deleted,name=:name,no=:no,state= :state,time=:time,type=:type,value=:value,update_timestamp=:updateTimestamp" +
                    " where merchant_id=:merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
            branchJdbcTemplate.batchUpdate(sql,params);
        }

        if(CollectionUtils.isNotEmpty(paramListInsert)){
            Map<String,?>[] params=new Map[paramListInsert.size()];
            for (int i = 0; i < paramListInsert.size(); i++) {
                params[i] = paramListInsert.get(i);
            }
            sql = "INSERT INTO charges(create_at,is_deleted,status,merchant_id,name,no,state,time,type,value,uuid,update_timestamp)\n" +
                    "VALUES(now(),:deleted,0,:merchantId,:name,:no,:state,:time,:type,:value,:uuid,:updateTimestamp)";
            branchJdbcTemplate.batchUpdate(sql,params);
        }
    }

    /**
     * 数据下发 付款方式
     * @param bIDs 分店ids
     * @param dataList 下发数据
     */
    public void updatePayment(List<Long> bIDs,List<Payment> dataList){
        if(CollectionUtils.isEmpty(bIDs) || CollectionUtils.isEmpty(dataList)){
            throw new BusinessRunTimeException("数据为空",10001);
        }

        //1.将分店id 转换成merchantIds
        Set<Long> merchantIDs = changeMerchants(bIDs);
        if(CollectionUtils.isEmpty(merchantIDs)){
            throw new BusinessRunTimeException("分店商户id 为空",10001);
        }
        //2.根据merchantid 查询单店系统中对应表的uuid和merchantID字段, 将获取到的数据转换为Map<Long, Set<String>> 格式 merchant -> Set<UUID>
        String sql = "select merchant_id,uuid from payment_types where merchant_id in (:merchantIds) ";
        QyMap map = QyMap.map("merchantIds",merchantIDs);
        List<Map<String,Object>> mapList = branchJdbcTemplate.queryForList(sql,map);
        //根据merchantId分组
        Map<Long, Set<String>> branchDataMap = mapList.stream()
                .map(QyMap::new)
                .filter(x->x.get("uuid")!=null)
                .collect(Collectors.groupingBy(x->x.getLong("merchant_id"), Collectors.mapping(x->x.getString("uuid"), Collectors.toSet())));
        //6.将转换后的merchantId SET集合遍历，
        // 遍历连锁店数据，
        // 依次判断数据元素uuid是否在对应单店系统的UUID的集合中存在，
        // 如果存在则update ... where merchant_id=? and update_timestamp<>? and uuid=?.  update_timestamp 取要下发数据的update_timestamp 值。
        // 否则插入数据
        Set<String> stringSet = null;
        List<QyMap> paramListUpdate = Lists.newArrayList();
        List<QyMap> paramListInsert = Lists.newArrayList();
        QyMap param = null;
        for (Long merchantID : merchantIDs) {
            stringSet = branchDataMap.get(merchantID);
            for (Payment payment : dataList) {
                param = QyMap.NEW();
                param.setv("merchantId",merchantID);
                param.setv("updateTimestamp",payment.getUpdateTimestamp());
                param.setv("uuid",payment.getUuid());
                param.setv("name",payment.getName());
                param.setv("type",getBranchPaymentType(payment.getType()));
                param.setv("state",payment.getState().getKey());
                param.setv("remark",payment.getRemark());
                param.setv("configs",payment.getParams());
                param.setv("deleteAble",payment.getDeleteAble());
                param.setv("hasPoint",payment.getIntegral());
                param.setv("deleted",payment.isDeleted());
                param.setv("recharge",payment.getRecharge());


                if(CollectionUtils.isNotEmpty(stringSet) && stringSet.contains(payment.getUuid())){
                    //update
                    paramListUpdate.add(param);
                }else {
                    //insert
                    paramListInsert.add(param);
                }
            }
        }

        //批量执行sql
        if(CollectionUtils.isNotEmpty(paramListUpdate)){
            Map<String,?>[] params=new Map[paramListUpdate.size()];
            for (int i = 0; i < paramListUpdate.size(); i++) {
                params[i] = paramListUpdate.get(i);
            }
            sql = "update payment_types set update_at = now(),is_deleted=:deleted,name = :name,remark=:remark,state=:state,type=:type,delete_able=:deleteAble,has_point=:hasPoint, update_timestamp = :updateTimestamp,configs=:configs,recharge=:recharge " +
                    "where merchant_id=:merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp ";
            branchJdbcTemplate.batchUpdate(sql,params);
        }

        if(CollectionUtils.isNotEmpty(paramListInsert)){
            Map<String,?>[] params=new Map[paramListInsert.size()];
            for (int i = 0; i < paramListInsert.size(); i++) {
                params[i] = paramListInsert.get(i);
            }
            sql = "INSERT INTO payment_types(create_at,is_deleted,status,merchant_id,configs,delete_able,has_point,name,remark,state,type,uuid,update_timestamp,recharge) " +
                    "VALUES(NOW(),:deleted,0,:merchantId,:configs,:deleteAble,:hasPoint,:name,:remark,:state,:type,:uuid,:updateTimestamp,:recharge)";
            branchJdbcTemplate.batchUpdate(sql,params);
        }
    }


    /**
     * 数据下发 辅助信息
     * @param bIDs 分店id
     * @param
     * @param dataList 备注信息
     */
    public void updateComment(List<Long> bIDs,List<Comment> dataList){
        if(CollectionUtils.isEmpty(bIDs) || CollectionUtils.isEmpty(dataList)){
            throw new BusinessRunTimeException("数据为空",10001);
        }

        //1.将分店id 转换成merchantIds
        Set<Long> merchantIDs = changeMerchants(bIDs);
        if(CollectionUtils.isEmpty(merchantIDs)){
            throw new BusinessRunTimeException("分店商户id 为空",10001);
        }
        //2.根据merchantid 查询单店系统中对应表的uuid和merchantID字段, 将获取到的数据转换为Map<Long, Set<String>> 格式 merchant -> Set<UUID>
        String sql = "select merchant_id,uuid from comments where merchant_id in (:merchantIds) ";
        QyMap map = QyMap.map("merchantIds",merchantIDs);
        List<Map<String,Object>> mapList = branchJdbcTemplate.queryForList(sql,map);
        //根据merchantId分组
        Map<Long, Set<String>> branchDataMap = mapList.stream()
                .map(QyMap::new)
                .filter(x->x.get("uuid")!=null)
                .collect(Collectors.groupingBy(x->x.getLong("merchant_id"), Collectors.mapping(x->x.getString("uuid"), Collectors.toSet())));

        //6.将转换后的merchantId SET集合遍历，
        // 遍历连锁店数据，
        // 依次判断数据元素uuid是否在对应单店系统的UUID的集合中存在，
        // 如果存在则update ... where merchant_id=? and update_timestamp<>? and uuid=?.  update_timestamp 取要下发数据的update_timestamp 值。
        // 否则插入数据
        Set<String> stringSet = null;
        List<QyMap> paramListUpdate = Lists.newArrayList();
        List<QyMap> paramListInsert = Lists.newArrayList();
        QyMap param = null;
        for (Long merchantID : merchantIDs) {
            stringSet = branchDataMap.get(merchantID);
            for (Comment comment : dataList) {
                param = QyMap.NEW();
                param.setv("merchantId",merchantID);
                param.setv("updateTimestamp",comment.getUpdateTimestamp());
                param.setv("uuid",comment.getUuid());
                param.setv("name",comment.getName());
                param.setv("type",getBranchCommentType(comment.getType()));
                param.setv("deleted",comment.isDeleted());
                if(CollectionUtils.isNotEmpty(stringSet) && stringSet.contains(comment.getUuid())){
                    //update
                    paramListUpdate.add(param);
                }else {
                    //insert
                    paramListInsert.add(param);
                }
            }
        }

        //批量执行sql
        if(CollectionUtils.isNotEmpty(paramListUpdate)){
            Map<String,?>[] params=new Map[paramListUpdate.size()];
            for (int i = 0; i < paramListUpdate.size(); i++) {
                params[i] = paramListUpdate.get(i);
            }
            sql = "UPDATE comments SET update_at = now(), is_deleted=:deleted,name = :name,type=:type,update_timestamp=:updateTimestamp " +
                    "where merchant_id=:merchantId and uuid = :uuid and update_timestamp <> :updateTimestamp";
            branchJdbcTemplate.batchUpdate(sql,params);

        }


        if(CollectionUtils.isNotEmpty(paramListInsert)){
            Map<String,?>[] params=new Map[paramListInsert.size()];
            for (int i = 0; i < paramListInsert.size(); i++) {
                params[i] = paramListInsert.get(i);
            }
            sql = "INSERT INTO comments (create_at,is_deleted,status,merchant_id,name,type,uuid,update_timestamp) " +
                    "VALUES(NOW(),:deleted,0,:merchantId,:name,:type,:uuid,:updateTimestamp)";
            branchJdbcTemplate.batchUpdate(sql,params);
        }
    }

    /**
     * 将分店ids 转换成 merchantIds
     * @param ids
     * @return
     */
    public Set<Long> changeMerchants(List<Long> ids){
        List<Branch> branchList = branchRepository.findAllById(ids);
        ids = branchList.stream().map(Branch::getMerchantId).collect(Collectors.toList());
        Set<Long> newIds = new HashSet<>(ids);
        return newIds;
    }

    /**
     * 辅助原因类型 转换成单店版的备注类型
     * @param type
     * @return
     */
    public String getBranchCommentType(CommentType type){
        switch (type){
            case FANJIE:
                return "THECHECKOUT";
            case TUICAI:
                return "FOODBACK";
            case MIANDAN:
                return "FREEOFCHARGE";
            case ZENGCAI:
                return "GIVEFOOD";
            case ZHEKOU:
                return "DISCOUNT";
            case KOUWEI:
                return "TASTE";
            case WAIMAIQUXIAO:
                return "TAKEOUT";
            default: return "";
        }
    }
    /**
     * 辅助原因类型 转换成单店版的支付类型
     * @param type
     * @return
     */
    public String getBranchPaymentType(PaymentType type){
        switch (type){
            case BANKCARD:
                return "BANKCARD";
            case COUPON:
                return "COUPON";
            case THIRDPARTY:
                return "THIRDPARTY";
            case CASHIER:
                return "SCANBAR";
            case CASH:
                return "CASH";
            case VIPCARD:
                return "MEMBER";
            case GUAZHANG:
                return "SUSPENDED";
            default: return "";
        }
    }



}